Документация / РусскийИсходный текст ↗

ruFFT Руководство пользователя

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

Вычислительные библиотеки · Тензорная платформа · 中文

ruFFT вычисляет БПФ и обратные преобразования реального сигнала на устройстве. Интерфейс rufft::tensor распределяет выходы; используйте rfft_launch и irfft_launch при непосредственном управлении привязками устройств.

1. Настройте зависимости

Пакет Cargo — ruda-fft; его имя для импорта в Rust — rufft. Функция tensor включает тензорные интерфейсы устройств. В этой конфигурации каталог приложения размещается рядом с исходным каталогом RUDA. См. раздел Начало работы для настройки NVIDIA.

[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. Прямое и обратное преобразование

Этот полный src/main.rs загружает четырехточечный сигнал F32, вычисляет его спектр и восстанавливает входные данные. Запустите cargo run из каталога приложения:

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(())
}

Четырехточечный сигнал создает три элемента разрешения: DC, один элемент положительной частоты и элемент Найквиста. Действительные и мнимые компоненты представляют собой отдельные тензоры, а не чередующиеся комплексные значения. Прямое преобразование ненормализовано; обратное включает нормализацию фактической длины FFT, поэтому не делите на длину снова.

В примере используется clone() для сохранения дескрипторов тензора для обратного преобразования. into_data_sync ожидает обратного чтения и возвращает данные хоста; он паникует при сбое чтения.

3. Параметры и выходные формы

Функция Параметры Возврат
rfft(signal, dim, n) Сигнал, ось отсчитывается от нуля, необязательная запрошенная длина Два тензора устройств (real, imag)
irfft(real, imag, dim, n) Реальная часть, мнимая часть, ось, дополнительная выходная длина Тензор устройства с действительным знаком

Для вычислений устройства используется F32; поставлять сигналы и спектры F32. dim должен быть меньше входного ранга. Компоненты обратного преобразования должны иметь соответствующую форму dtype и устройство. Эти интерфейсы возвращают тензоры, а не Result; неудачные аргументированные утверждения или вызывает панику.

Для запрошенной длины n фактическая длина N по FFT представляет собой наименьшую степень двойки, большую или равную n:

Ввод/вызов Фактическая длина преобразования Длина вывода по размеру
Длина 8, rfft(..., None) 8 5
Длина 8, rfft(..., Some(6)) 8; сохранить только первые 6 входных точек и нулевую панель 5
Длина 6, rfft(..., None) 8, дополненный нулями 5
5 частотных отсчётов, irfft(..., None) 8 8
5 частотных отсчётов, irfft(..., Some(6)) 8 6

Таким образом, Some(6) не запрашивает шеститочечный DFT. Для прохождения исходного шеститочечного сигнала туда и обратно передайте Some(6) обратному сигналу, чтобы удалить две дополненные хвостовые точки.

4. Пакеты и многомерный ввод

Оси, отличные от dim, являются размерами партии. Например, преобразование [batch, channels, 1024] по dim=2 создает действительные и мнимые тензоры формы [batch, channels, 513].

Эта функция повторно использует предыдущий импорт rfft и принимает тензор устройства, не читая его обратно:

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))
}

Одиночный вызов rfft преобразует только выбранную ось, а не весь многомерный FFT. Не рассматривайте отдельные действительные и мнимые компоненты как полные комплексные сигналы, передавая каждый из них независимо в rfft.

5. Буферы и выполнение

Тензорные интерфейсы выделяют выходные данные и при необходимости выполняют заполнение и обрезку. Фактическая длина выше 4096 автоматически использует промежуточный путь без изменения вызова. Чтобы самостоятельно управлять выходными буферами, интерфейсы запуска принимают значения клиента, ввода/вывода TensorBinding, dim и StorageType, возвращая Result<(), LaunchError>. Выделите соответствующие выходные макеты для фактического N.

Чтобы избежать материализации ввода с нулевым заполнением при управлении буферами, используйте следующие точки входа:

Функция Дополнительный параметр длины
rfft_launch_padded(client, signal, real, imag, dim, signal_len, dtype) Считывает только первые элементы сигнала signal_len, а остальные обрабатывает как ноль; N выводится из длины выходного спектра
irfft_launch_padded(client, real, imag, signal, dim, spec_bins, dtype) Считывает только первые элементы разрешения частоты spec_bins, а остальные обрабатывает как ноль; N зависит от длины выходного сигнала

N должно быть степенью двойки не менее 2, а действительные и воображаемые фигуры должны совпадать. signal_len не может превышать длину входной оси или N. spec_bins должно быть не менее 1 и не может превышать длину входной оси спектра или N / 2 + 1. Выходные буферы по-прежнему требуют полного выделения; эти интерфейсы позволяют избежать материализации входного хвоста с нулевым дополнением.

API Ссылка: Тензорный интерфейс, Прямой запуск, Обратный запуск.