Skip to content

Commit

Permalink
Merge pull request #20 from QuState/hotfix
Browse files Browse the repository at this point in the history
Hotfix
  • Loading branch information
smu160 authored Apr 11, 2024
2 parents d1701ea + 3c61c97 commit ad6fed5
Show file tree
Hide file tree
Showing 6 changed files with 26 additions and 23 deletions.
13 changes: 8 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,22 +11,25 @@ Transform (FFT) library written in pure Rust.

## Features

- Simple implementation using a single, general-purpose FFT algorithm
- Simple implementation using the Cooley-Tukey FFT algorithm
- Performance on par with other Rust FFT implementations
- Zero `unsafe` code
- Takes advantage of latest CPU features up to and including AVX-512, but performs well even without them
- Takes advantage of latest CPU features up to and including `AVX-512`, but performs well even without them
- Optional parallelization of some steps to 2 threads (with even more planned)
- 2x lower memory usage than [RustFFT](https://crates.io/crates/rustfft/)
- Python bindings (via [PyO3](https://github.com/PyO3/pyo3))

## Limitations

- Only supports input with a length of `2^n` (i.e., a power of 2) -- input should be padded with zeros to the next power
of 2
- No runtime CPU feature detection (yet). Right now achieving the highest performance requires compiling
with `-C target-cpu=native` or [`cargo multivers`](https://github.com/ronnychevalier/cargo-multivers).
with `-C target-cpu=native` or [`cargo multivers`](https://github.com/ronnychevalier/cargo-multivers)
- Requires nightly Rust compiler due to use of portable SIMD

## Planned features

- Bluestein's algorithm (to handle arbitrary sized FFTs)
- Runtime CPU feature detection
- More multi-threading
- More work on cache-optimal FFT
Expand All @@ -39,7 +42,7 @@ years or so).
The two major bottlenecks in FFT are the **CPU cycles** and **memory accesses**.

We picked an efficient, general-purpose FFT algorithm. Our implementation can make use of latest CPU features such as
AVX-512, but performs well even without them.
`AVX-512`, but performs well even without them.

Our key insight for speeding up memory accesses is that FFT is equivalent to applying gates to all qubits in `[0, n)`.
This creates the opportunity to leverage the same memory access patterns as
Expand Down Expand Up @@ -130,7 +133,7 @@ submit a pull request. Follow the contribution guidelines outlined in the CONTRI

PhastFT is licensed under MIT or Apache 2.0 license, at your option.

## PhastFT vs RustFFT
## PhastFT vs. RustFFT

[RustFFT](https://crates.io/crates/rustfft/) is another excellent FFT implementation in pure Rust.
RustFFT and PhastFT make different trade-offs.
Expand Down
Binary file removed pyphastft/32_bins_demo.mov
Binary file not shown.
7 changes: 4 additions & 3 deletions pyphastft/example.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import matplotlib.pyplot as plt
import numpy as np
from numpy.fft import fft

from pyphastft import fft
# from pyphastft import fft


def main():
Expand All @@ -16,7 +17,7 @@ def main():
) # Adjusted time vector

# Generate the signal
s_re = 2 * np.sin(2 * np.pi * t) + np.sin(2 * np.pi * 10 * t)
s_re = 2 * np.sin(2 * np.pi * t + 1) + np.sin(2 * np.pi * 10 * t + 1)
s_im = np.ascontiguousarray([0.0] * len(s_re), dtype=np.float64)

# Plot the original signal
Expand All @@ -30,7 +31,7 @@ def main():
plt.legend()

# Perform FFT
fft(s_re, s_im, direction="f")
s_re = fft(s_re)

# Plot the magnitude spectrum of the FFT result
plt.subplot(2, 1, 2)
Expand Down
4 changes: 2 additions & 2 deletions pyphastft/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use numpy::PyReadwriteArray1;
use phastft::{fft as fft_rs, planner::Direction};
use phastft::{fft_64 as fft_64_rs, planner::Direction};
use pyo3::prelude::*;

#[pyfunction]
Expand All @@ -11,7 +11,7 @@ fn fft(mut reals: PyReadwriteArray1<f64>, mut imags: PyReadwriteArray1<f64>, dir
Direction::Reverse
};

fft_rs(
fft_64_rs(
reals.as_slice_mut().unwrap(),
imags.as_slice_mut().unwrap(),
dir,
Expand Down
20 changes: 10 additions & 10 deletions pyphastft/vis_qt.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
from pyphastft import fft
import sys

import numpy as np
import pyaudio
import pyqtgraph as pg
from pyphastft import fft
from pyqtgraph.Qt import QtWidgets, QtCore
import sys


class RealTimeAudioSpectrum(QtWidgets.QWidget):
Expand All @@ -28,7 +29,7 @@ def init_ui(self):
self.plot_widget.setBackground("k")
self.plot_item = self.plot_widget.getPlotItem()
self.plot_item.setTitle(
"Real-Time Audio Spectrum Visualizer\npowered by PhastFT",
"Real-Time Audio Spectrum Visualizer powered by PhastFT",
color="w",
size="16pt",
)
Expand Down Expand Up @@ -79,10 +80,10 @@ def init_audio_stream(self):
def audio_callback(self, in_data, frame_count, time_info, status):
audio_data = np.frombuffer(in_data, dtype=np.float32)
reals = np.zeros(self.n_fft_bins)
imaginaries = np.zeros(self.n_fft_bins)
imags = np.zeros(self.n_fft_bins)
reals[: len(audio_data)] = audio_data # Fill the reals array with audio data
fft(reals, imaginaries, direction="f")
fft_magnitude = np.sqrt(reals**2 + imaginaries**2)[: self.n_fft_bins // 2]
fft(reals, imags, direction="f")
fft_magnitude = np.sqrt(reals**2 + imags**2)[: self.n_fft_bins // 2]

# Aggregate or interpolate FFT data to fit into display bins
new_fft_data = np.interp(
Expand All @@ -93,13 +94,12 @@ def audio_callback(self, in_data, frame_count, time_info, status):

# Apply exponential moving average filter
self.ema_fft_data = self.ema_fft_data * self.smoothing_factor + new_fft_data * (
1 - self.smoothing_factor
1.0 - self.smoothing_factor
)
return (in_data, pyaudio.paContinue)
return in_data, pyaudio.paContinue

def update(self):
if hasattr(self, "ema_fft_data"):
self.bar_graph.setOpts(height=self.ema_fft_data, width=self.bar_width)
self.bar_graph.setOpts(height=self.ema_fft_data, width=self.bar_width)

def closeEvent(self, event):
self.stream.stop_stream()
Expand Down
5 changes: 2 additions & 3 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,7 @@ macro_rules! impl_fft_for {
///
/// # Panics
///
/// Panics if `reals.len() != imags.len()` or if `reals.len()` and `imags.len()` are not a power of
/// 2
/// Panics if `reals.len() != imags.len()`, or if the input length is _not_ a power of 2.
///
/// ## References
/// <https://inst.eecs.berkeley.edu/~ee123/sp15/Notes/Lecture08_FFT_and_SpectAnalysis.key.pdf>
Expand Down Expand Up @@ -77,7 +76,7 @@ macro_rules! impl_fft_with_opts_and_plan_for {
///
/// # Panics
///
/// Panics if `reals.len() != imags.len()`, or if the input length is *not* a power of 2.
/// Panics if `reals.len() != imags.len()`, or if the input length is _not_ a power of 2.
pub fn $func_name(
reals: &mut [$precision],
imags: &mut [$precision],
Expand Down

0 comments on commit ad6fed5

Please sign in to comment.