Dokumentation / DeutschQuelltext ansehen ↗

ruFFT Benutzerhandbuch

English | 简体中文 | 日本語 | Deutsch | Русский

Computerbibliotheken · Tensor-Framework · 中文

ruFFT berechnet Realsignal-FFTs und inverse Transformationen auf dem Gerät. Die rufft::tensor-Schnittstelle weist Ausgänge zu; Verwenden Sie rfft_launch und irfft_launch, wenn Sie Gerätebindungen direkt verwalten.

1. Abhängigkeiten konfigurieren

Das Cargo-Paket ist ruda-fft; Sein Rust-Importname ist rufft. Die Funktion tensor ermöglicht Geräte-Tensor-Schnittstellen. Diese Konfiguration platziert das Anwendungsverzeichnis neben dem RUDA-Quellverzeichnis. Informationen zum NVIDIA-Setup finden Sie unter Erste Schritte.

[dependencies]
rufft = { package = "ruda-fft", path = "../RUDA/ruFFT", default-features = false, features = ["std", "tensor"] }
ruda-core = { path = "../RUDA/ruda-core", default-features = false, features = ["std", "tensor-host-data"] }
ruda-kernel = { path = "../RUDA/ruda-kernel", default-features = false, features = ["frontend-std", "device-tensor"] }
ruda-driver-cuda = { path = "../RUDA/ruda-driver-cuda", default-features = false, features = ["std"] }

2. Vorwärts- und Rücktransformationen

Dieser vollständige src/main.rs lädt ein Vierpunktsignal F32 hoch, berechnet sein Spektrum und rekonstruiert die Eingabe. Führen Sie cargo run aus dem Anwendungsverzeichnis aus:

use ruda_core::tensor::data::TensorData;
use ruda_driver_cuda::{CudaDevice, CudaRuntime};
use ruda_kernel::tensor::{readback::into_data_sync, transfer::from_data};
use rufft::tensor::{irfft, rfft};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let device = CudaDevice::default();
    let input = vec![1.0f32, 0.0, -1.0, 0.0];
    let signal = from_data::<CudaRuntime>(TensorData::new(input.clone(), [4]), &device);
    let (real, imag) = rfft(signal, 0, None);

    let re = into_data_sync(real.clone()).to_vec::<f32>()?;
    let im = into_data_sync(imag.clone()).to_vec::<f32>()?;
    for (actual, expected) in re.iter().zip([0.0f32, 2.0, 0.0]) {
        assert!((actual - expected).abs() < 1e-5);
    }
    assert!(im.iter().all(|value| value.abs() < 1e-5));

    let restored = irfft(real, imag, 0, Some(input.len()));
    let restored = into_data_sync(restored).to_vec::<f32>()?;
    for (actual, expected) in restored.iter().zip(input) {
        assert!((actual - expected).abs() < 1e-5);
    }
    println!("real={re:?}, imag={im:?}, restored={restored:?}");
    Ok(())
}

Ein Vierpunktsignal erzeugt drei Bins: DC, ein Bin mit positiver Frequenz und Nyquist. Real- und Imaginärkomponenten sind separate Tensoren, keine verschachtelten komplexen Werte. Die Vorwärtstransformation ist nicht normalisiert; Die Umkehrung beinhaltet die Normalisierung für die tatsächliche FFT-Länge, daher nicht erneut durch die Länge dividieren.

Das Beispiel verwendet clone(), um Tensor-Handles für die inverse Transformation beizubehalten. into_data_sync wartet auf das Zurücklesen und gibt Host-Daten zurück; Es gerät in Panik, wenn der Rücklesefehler fehlschlägt.

3. Parameter und Ausgabeformen

Funktion Parameter Gibt zurück
rfft(signal, dim, n) Signal, nullbasierte Achse, optional angeforderte Länge Zwei Gerätetensoren (real, imag)
irfft(real, imag, dim, n) Realteil, Imaginärteil, Achse, optionale Ausgabelänge Ein reeller Gerätetensor

Geräteberechnung verwendet F32; Bereitstellung von F32-Signalen und -Spektren. dim muss kleiner als der Eingaberang sein. Inverse Transformationskomponenten müssen eine passende Form, dtype und ein Gerät haben. Diese Schnittstellen geben Tensoren anstelle von Result zurück; Argumentationsbehauptungen scheitern oder Panik auslöst.

Für die angeforderte Länge n ist die tatsächliche FFT-Länge N die kleinste Zweierpotenz größer oder gleich n:

Eingabe/Aufruf Tatsächliche Transformationslänge Ausgabelänge entlang Bemaßung
Länge 8, rfft(..., None) 8 5
Länge 8, rfft(..., Some(6)) 8; Behalten Sie nur die ersten 6 Eingabepunkte und den Nullpunkt bei 5
Länge 6, rfft(..., None) 8, mit Nullen aufgefüllt 5
5 Frequenzbins, irfft(..., None) 8 8
5 Frequenzbins, irfft(..., Some(6)) 8 6

Somit fordert Some(6) keinen Sechspunkt-DFT an. Für einen Roundtrip eines ursprünglichen Sechspunktsignals übergeben Sie Some(6) an die Umkehrung, um die beiden gepolsterten Endpunkte zu entfernen.

4. Stapel und mehrdimensionale Eingabe

Andere Achsen als dim sind Chargenmaße. Beispielsweise erzeugt die Transformation von [batch, channels, 1024] entlang dim=2 reale und imaginäre Tensoren der Form [batch, channels, 513].

Diese Funktion verwendet den vorherigen rfft-Import wieder und akzeptiert einen Gerätetensor, ohne ihn zurückzulesen:

use ruda_kernel::{dsl::Runtime, tensor::RudaTensor};

fn batched_rfft<R: Runtime>(
    signals: RudaTensor<R>,
    dim: usize,
    length: usize,
) -> (RudaTensor<R>, RudaTensor<R>) {
    rfft(signals, dim, Some(length))
}

Ein einzelner rfft-Aufruf transformiert nur die ausgewählte Achse, nicht einen gesamten mehrdimensionalen FFT. Behandeln Sie die getrennten Real- und Imaginärkomponenten nicht als vollständige komplexe Signale, indem Sie sie jeweils unabhängig an rfft übergeben.

5. Puffer und Ausführung

Tensorschnittstellen weisen Ausgänge zu und führen bei Bedarf Auffüllen und Zuschneiden durch. Tatsächliche Längen über 4096 verwenden automatisch den bereitgestellten Pfad, ohne den Aufruf zu ändern. Um Ausgabepuffer selbst zu verwalten, akzeptieren die Startschnittstellen einen Client, geben TensorBinding-Werte, Dim und StorageType ein/aus und geben Result<(), LaunchError> zurück. Ordnen Sie passende Ausgabelayouts für das tatsächliche N zu.

Um zu vermeiden, dass beim Verwalten von Puffern Eingaben mit Nullen aufgefüllt werden, verwenden Sie diese Einstiegspunkte:

Funktion Zusätzlicher Längenparameter
rfft_launch_padded(client, signal, real, imag, dim, signal_len, dtype) Liest nur die ersten signal_len-Signalelemente und behandelt den Rest als Null; N wird aus der Länge des Ausgangsspektrums abgeleitet
irfft_launch_padded(client, real, imag, signal, dim, spec_bins, dtype) Liest nur die ersten spec_bins-Frequenzintervalle und behandelt den Rest als Null; N ergibt sich aus der Länge des Ausgangssignals

N muss eine Zweierpotenz von mindestens 2 sein und reale/imaginäre Formen müssen übereinstimmen. signal_len darf die Länge der Eingabeachse oder N nicht überschreiten. spec_bins muss mindestens 1 sein und darf die Länge der Eingabespektrumsachse oder N / 2 + 1 nicht überschreiten. Ausgabepuffer erfordern weiterhin eine vollständige Zuweisung; Diese Schnittstellen vermeiden die Materialisierung des mit Nullen aufgefüllten Eingabeendes.

API Referenz: Tensor-Schnittstelle, Vorwärtsstart, Inverser Start.