ruda-fft 0.1.21

Fast Fourier transforms for Ruda.
Documentation
# ruFFT

[English](../../README.md) | [简体中文](../zh/README.md) | [日本語](../ja/README.md) | [Deutsch](../de/README.md) | **Русский**

**Английский** | [简体中文](../zh/README.md)

Быстрое преобразование Фурье для Ruda.

- Cargo пакет: `ruFFT`
- Крейт Rust: `rufft`

## Feature

| Feature |Операции|
| --- | --- |
|`tensor`|БПФ реальных сигналов и обратные преобразования тензоров устройств|

Используйте `rufft::tensor::{rfft, irfft}` для выделения выходов преобразования или `rfft_launch` и `irfft_launch` для непосредственной работы с привязками устройств.

## Краткое руководство

Сборка из рабочей области RUDA:

```sh
git clone https://github.com/shuqi2077/RUDA.git
cd RUDA
cargo build --release --locked -p ruda-fft --no-default-features --features std,tensor
```

## Документация

- [Руководство пользователя](../../../docs/ru/libraries/rufft.md)
- [Настройка среды](../../../docs/ru/getting-started.md)
- [Функции Cargo](../../Cargo.toml) · [Экспорт модулей](../../src/lib.rs)

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

[Вычислительные библиотеки](../../../docs/ru/libraries/README.md) · [Тензорная платформа](../../../docs/ru/tensor-framework.md) · [中文](../zh/README.md)

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

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

Пакет Cargo — `ruFFT`; его имя для импорта в Rust — `rufft`. Функция `tensor` включает тензорные интерфейсы устройств. В этой конфигурации каталог приложения размещается рядом с исходным каталогом `RUDA`. См. раздел [Начало работы](../../../docs/ru/getting-started.md) для настройки NVIDIA.

```toml
[dependencies]
rufft = { package = "ruFFT", 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` из каталога приложения:

```rust
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 = None` `rfft` использует входную длину по размеру. В противном случае он сначала усекает или дополняет нулями до n, а затем дополняет нулями до N.
- Длина прямого вывода по dim равна `N / 2 + 1`; остальные размеры не изменяются.
- С `n = None` `irfft` использует `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` и принимает тензор устройства, не читая его обратно:

```rust
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 Ссылка: [Тензорный интерфейс](../../src/tensor.rs), [Прямой запуск](../../src/fft/rfft.rs), [Обратный запуск](../../src/fft/irfft.rs).