ruRAND 0.1.18

Random number generation for Ruda.
Documentation
# ruRAND

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

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

Генерация случайных чисел для Ruda.

- Cargo пакет: `ruRAND`
- Крейт Rust: `rurand`

## Feature

| Feature |Операции|
| --- | --- |
|`tensor`|Равномерное, нормальное распределение и распределение Бернулли на тензорах устройств|

Используйте `rurand::tensor::{random_uniform, random_normal, random_bernoulli}` для выделения тензоров или функций в корне крейта для заполнения существующей памяти устройства. `rurand::seed` устанавливает общее случайное начальное число.

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

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

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

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

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

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

[Вычислительные библиотеки](../../../docs/ru/libraries/README.md) · [Среда выполнения API](../../../docs/ru/runtime-api.md) · [中文](../zh/README.md)

ruRAND генерирует тензоры устройств с равномерным, нормальным распределением и распределением Бернулли. Используйте `rurand::tensor` для выделения новых тензоров или одноименных функций в корне крейта для заполнения существующей памяти устройства.

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

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

```toml
[dependencies]
rurand = { package = "ruRAND", path = "../RUDA/ruRAND", 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 формы `[2, 3]` и воспроизводит вызов, сбрасывая начальное число. Запустите `cargo run` из каталога приложения:

```rust
use ruda_core::tensor::DType;
use ruda_driver_cuda::{CudaDevice, CudaRuntime};
use ruda_kernel::tensor::readback::into_data_sync;
use rurand::tensor::{
    random_bernoulli, random_like_uniform, random_normal, random_uniform,
};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let device = CudaDevice::default();
    rurand::seed(42);
    let uniform = random_uniform::<CudaRuntime>([2, 3].into(), &device, 0.0, 1.0, DType::F32);
    let first = into_data_sync(uniform.clone()).to_vec::<f32>()?;

    rurand::seed(42);
    let repeated = random_uniform::<CudaRuntime>([2, 3].into(), &device, 0.0, 1.0, DType::F32);
    let repeated = into_data_sync(repeated).to_vec::<f32>()?;
    assert_eq!(first, repeated);
    assert!(first.iter().all(|&x| (0.0..1.0).contains(&x)));

    let normal = random_normal::<CudaRuntime>([2, 3].into(), &device, 0.0, 1.0, DType::F32);
    let mask = random_bernoulli::<CudaRuntime>([2, 3].into(), &device, 0.25, DType::F32);
    let noise = random_like_uniform(&uniform, -0.1, 0.1, DType::F32);

    let mask = into_data_sync(mask).to_vec::<f32>()?;
    assert!(mask.iter().all(|&x| x == 0.0 || x == 1.0));
    println!("uniform={first:?}");
    println!("normal={:?}", into_data_sync(normal).to_vec::<f32>()?);
    println!("mask={mask:?}");
    println!("noise={:?}", into_data_sync(noise).to_vec::<f32>()?);
    Ok(())
}
```

`random_like_uniform` берет из эталона только форму и устройство. Он выделяет новый тензор без изменения и копирования опорных значений. Его последний аргумент явно выбирает выход dtype.

`random_bernoulli` возвращает нули и единицы в выбранном dtype, а не автоматически созданную логическую маску. В этом примере возвращаются значения F32 0.0 и 1.0.

### 3. Параметры и распределения

Первые три тензорные функции имеют общие параметры `shape: Shape`, `device: &R::Device` и последний параметр `dtype: DType`. Возвращенный `RudaTensor<R>` имеет указанную форму dtype и устройство.

|Порядок функций и параметров|Параметры распределения|
| --- | --- |
|`random_uniform(shape, device, lower_bound, upper_bound, dtype)`|f32 нижняя и верхняя границы|
|`random_normal(shape, device, mean, std, dtype)`|f32 среднее и стандартное отклонение; стандартное значение не является отклонением|
|`random_bernoulli(shape, device, probability, dtype)`|f32 вероятность возврата 1|
|`random_like_uniform(&reference, lower_bound, upper_bound, dtype)`|Базовый тензор, границы f32, выход dtype|

Предоставьте конечные параметры, соответствующие распределению: нижняя граница ниже верхней границы, неотрицательное нормальное стандартное отклонение и вероятность Бернулли в `[0, 1]`. Эти интерфейсы не проверяют эти диапазоны через `Result`; не используйте недопустимые параметры для запроса возврата ошибки.

При генерации однородного результата сначала создается F32 `u ∈ [0, 1)`, вычисляется `lower_bound + (upper_bound - lower_bound) × u`, а затем выполняется приведение к выходным данным dtype. Случай F32 `[0, 1)` исключает 1. Масштабирование до других интервалов или преобразование в более низкую точность может привести к округлению значения вблизи верхней границы этой границы.

Обычное генерирование использует преобразование Бокса-Мюллера FP32 перед приведением к выходу dtype. Выбор хранилища F64 не увеличивает внутреннюю точность случайных чисел с плавающей запятой. Бернулли сравнивает `u < probability`, поэтому вероятность 0 дает все нули, а вероятность 1 дает все единицы.

### 4. Начальные значения и порядок вызова

`rurand::seed(seed: u64)` сбрасывает случайное состояние общего хоста. Каждый вызов поколения извлекает новые семена из этого состояния и продвигает его:

- Задайте начальное число один раз, чтобы инициализировать последовательность, а затем сгенерируйте последующие пакеты.
- Чтобы воспроизвести последовательность, сбросьте то же начальное число и сохраните порядок вызова, форму, dtype и конфигурацию устройства.
- Не сбрасывайте одно и то же начальное значение перед каждым обучающим пакетом, если не предполагается повторение случайных входных данных.
- Параллельные потоки разделяют это состояние; чередование влияет на то, какие начальные числа получает каждый вызов. Это не отдельный объект-генератор для каждого потока или устройства.

Приведенное выше сравнение повторов использует один процесс, одно устройство и соответствующие аргументы. Сопоставление начальных чисел само по себе не подразумевает поэлементное равенство с другой случайной библиотекой или серверной частью.

### 5. Заполните существующий буфер.

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

```rust
use ruda_kernel::{
    dsl::{Runtime, prelude::LaunchError},
    tensor::RudaTensor,
};

fn fill_uniform<R: Runtime>(
    output: RudaTensor<R>,
    lower: f32,
    upper: f32,
) -> Result<RudaTensor<R>, LaunchError> {
    rurand::random_uniform(
        &output.client,
        lower,
        upper,
        output.clone().binding(),
        output.dtype.into(),
    )?;
    Ok(output)
}
```

Эта функция не вызывает тензорный распределитель. Другие дескрипторы, совместно использующие это хранилище, также наблюдают за записью. Соответствующими функциями для нормальных значений и значений Бернулли являются `rurand::random_normal(&client, mean, std, binding, dtype)` и `rurand::random_bernoulli(&client, probability, binding, dtype)`.

Функции тензорного уровня вызывают панику, если при запуске возвращается ошибка; базовая точка входа выше возвращает `Result<(), LaunchError>`. Успешная отправка не означает, что выполнение GPU завершено. Считайте тензор обратно или дождитесь синхронизации клиента. `into_data_sync` паникует при сбое чтения; используйте асинхронный `into_data(tensor).await` для распространения ошибок обратного чтения.

API Ссылка: [Тензорные интерфейсы](../../src/tensor/mod.rs), [Исходное состояние](../../src/state.rs), [Распределения](../../src/distributions/mod.rs).