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:
- При использовании
n = Nonerfftиспользует входную длину по размеру. В противном случае он сначала усекает или дополняет нулями до n, а затем дополняет нулями до N. - Длина прямого вывода по dim равна
N / 2 + 1; остальные размеры не изменяются. - С
n = Noneirfftиспользует2 × (bin count - 1). Явное число n указывает возвращаемую длину. - Инверсия сначала усекает или дополняет нулями обе компоненты спектра до элементов
N / 2 + 1, вычисляет инверсию N-точек, а затем обрезает до n. - Запрошенная длина должна быть не менее 2; одноточечное преобразование не проходит проверку длины ядра устройства.
| Ввод/вызов | Фактическая длина преобразования | Длина вывода по размеру |
|---|---|---|
Длина 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 Ссылка: Тензорный интерфейс, Прямой запуск, Обратный запуск.