Dokumentation / DeutschQuelltext ansehen ↗

ruRAND Benutzerhandbuch

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

Compute-Bibliotheken · Laufzeit API · 中文

ruRAND generiert Gerätetensoren mit gleichmäßiger, normaler und Bernoulli-Verteilung. Verwenden Sie rurand::tensor, um neue Tensoren zuzuweisen, oder die gleichnamigen Funktionen im Crate-Stamm, um den vorhandenen Gerätespeicher zu füllen.

1. Abhängigkeiten konfigurieren

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

[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. Generieren Sie zufällige Tensoren

Dieser vollständige src/main.rs generiert F32-Tensoren der Form [2, 3] und spielt einen Aufruf durch Zurücksetzen des Startwerts ab. Führen Sie cargo run aus dem Anwendungsverzeichnis aus:

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 übernimmt nur Form und Gerät aus der Referenz. Es weist einen neuen Tensor zu, ohne die Referenzwerte zu ändern oder zu kopieren. Sein letztes Argument wählt explizit die Ausgabe dtype aus.

random_bernoulli gibt Nullen und Einsen im ausgewählten dtype zurück, keine automatisch erstellte boolesche Maske. In diesem Beispiel werden die F32-Werte 0.0 und 1.0 zurückgegeben.

3. Parameter und Verteilungen

Die ersten drei Tensorfunktionen teilen sich shape: Shape, device: &R::Device und einen letzten dtype: DType-Parameter. Der zurückgegebene RudaTensor<R> hat die angegebene Form, dtype und das angegebene Gerät.

Funktions- und Parameterreihenfolge Verteilungsparameter
random_uniform(shape, device, lower_bound, upper_bound, dtype) f32 untere und obere Grenzen
random_normal(shape, device, mean, std, dtype) f32 Mittelwert und Standardabweichung; Standard ist keine Varianz
random_bernoulli(shape, device, probability, dtype) f32 Rückgabewahrscheinlichkeit 1
random_like_uniform(&reference, lower_bound, upper_bound, dtype) Referenztensor, f32-Grenzen, Ausgabe dtype

Geben Sie endliche Parameter an, die mit der Verteilung übereinstimmen: Untergrenze unter Obergrenze, nichtnegative normale Standardabweichung und Bernoulli-Wahrscheinlichkeit in [0, 1]. Diese Schnittstellen validieren diese Bereiche nicht über Result; Verwenden Sie keine ungültigen Parameter, um eine Fehlerrückgabe anzufordern.

Die einheitliche Generierung erzeugt zunächst F32 u ∈ [0, 1), berechnet lower_bound + (upper_bound - lower_bound) × u und wandelt sie dann in die Ausgabe dtype um. Der Fall F32 [0, 1) schließt 1 aus. Die Skalierung auf andere Intervalle oder die Konvertierung in eine niedrigere Genauigkeit kann einen Wert in der Nähe der Obergrenze auf diese Grenze runden.

Die normale Generierung verwendet eine FP32 Box-Muller-Transformation vor der Umwandlung in die Ausgabe dtype. Durch die Auswahl des F64-Speichers wird die interne Zufalls-Gleitkommagenauigkeit nicht erhöht. Bernoulli vergleicht u < probability, sodass Wahrscheinlichkeit 0 alle Nullen und Wahrscheinlichkeit 1 alle Einsen erzeugt.

4. Seeds und Aufrufreihenfolge

rurand::seed(seed: u64) setzt den zufälligen Status des gemeinsam genutzten Hosts zurück. Jeder Generationsaufruf zieht neue Samen aus diesem Zustand und treibt ihn voran:

Der obige Wiedergabevergleich verwendet einen Prozess, ein Gerät und passende Argumente. Übereinstimmende Seeds allein bedeuten keine elementare Gleichheit mit einer anderen zufälligen Bibliothek oder einem anderen Backend.

5. Füllen Sie einen vorhandenen Puffer

Verwenden Sie Crate-Root-Startfunktionen, um eine Ausgabezuordnung wiederzuverwenden. Diese Funktion nimmt einen bereits zugewiesenen F32-Gerätetensor, schreibt Zufallswerte in seinen Speicher und gibt ihn zurück:

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

Die Funktion ruft keinen Tensor-Allokator auf. Andere Handles, die diesen Speicher gemeinsam nutzen, beobachten die Schreibvorgänge ebenfalls. Entsprechende Funktionen für Normal- und Bernoulli-Werte sind rurand::random_normal(&client, mean, std, binding, dtype) und rurand::random_bernoulli(&client, probability, binding, dtype).

Funktionen auf Tensorebene geraten in Panik, wenn beim Starten ein Fehler zurückgegeben wird. Der zugrunde liegende Einstiegspunkt oben gibt Result<(), LaunchError> zurück. Eine erfolgreiche Übermittlung bedeutet nicht, dass die Ausführung von GPU abgeschlossen ist. Lesen Sie den Tensor zurück oder warten Sie auf die Client-Synchronisierung. into_data_sync gerät bei Rücklesefehler in Panik; Verwenden Sie asynchrones into_data(tensor).await, um Rücklesefehler weiterzugeben.

API Referenz: Tensorschnittstellen, Seed-Status, Verteilungen.