Dokumentation / DeutschQuelltext ansehen ↗

ruDNN Benutzerhandbuch

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

Computerbibliotheken · ruBLAS · Tensoren und Frameworks · 中文

1. Übersicht und Funktionen

ruDNN bietet neuronale Netzwerkoperationen. Das Cargo-Paket ist ruDNN und die Rust-Crate ist rudnn.

Feature Operationen
tensor-attention Tensor-Aufmerksamkeit
tensor-paged-attention Seitenbasierte MHA/GQA/MLA
tensor-convolution Tensorfaltung
pooling, interpolation Pooling und Interpolation
grid-sample, ctc Rasterstichprobe und CTC
tensor-moe Gerät MoE Routing und Expertenberechnung
tensor-normalization Universelle Gerätenormalisierung für Modellebenen
tensor-gated-delta Gated-Delta-Berechnung für Hybridarchitekturen wie Qwen3.5

Aufmerksamkeit und Faltung verfügen jeweils über entsprechende Autotune-Funktionen. Siehe Cargo.toml und Modulexporte.

2. Attention und Faltung

Attention

rudnn::attention::tensor::attention akzeptiert Abfrage, Schlüssel, Wert, optionale Maske, optionales attn_bias, AttentionModuleOptions und AttentionStrategy. Es gibt einen Gerätetensor oder AttentionSetupError zurück.

Die Strategien umfassen FlashBlackboxAccelerated, FlashUnit, Fallback und bei aktiviertem Feature Autotune. Ohne Autotuning ist Fallback der Standard, mit Autotuning Autotune. Fallback verwendet mehrere Kernels auf demselben Gerät, kein CPU-Backend.

Passen Sie Layout, Maske und Präzision an die ausgewählte Strategie an. Siehe die Attention-Schnittstelle.

Faltung

rudnn::convolution::tensor::conv_forward übernimmt Eingabe, Gewicht, optional bias, ConvOptions und ConvStrategy. Es gibt einen Gerätetensor oder ConvSetupError zurück. Es konvertiert Eingaben zur Ausführung in das Channel-Last-Layout und konvertiert die Ausgabe zurück. conv_forward_nhwc verwendet direkt das Channels-Last-Layout.

Zu den Strategien gehören Direct, ImplicitGemm und optional Autotune. Der Einstiegspunkt verwendet Direct für die dreidimensionale F32-Faltung. Die gruppierte Faltung verwendet auch Direct, wenn ImplicitGemm ausgewählt ist. Der Strategieparameter ist daher nicht immer eine strikte Anforderung, einen Algorithmus beizubehalten.

Das gleiche Modul stellt conv_data_backward und conv_weight_backward bereit. Überprüfen Sie Form, Optionen und Ausführungsanforderungen für jede Richtung. Siehe die Faltungsschnittstelle.

3. MoE-Workflow

rudnn::moe stellt diese lokale Berechnungssequenz bereit:

Eingabe-Logits → softmax/top-k → kompakte Verteilung → SwiGLU-Experten → gewichtete Zusammenführung.

API Zweck
route(logits, RoutingOptions) Erstellt ein RoutingPlan
RoutingPlan::expert_indices(), weights() Greift auf ausgewählte Experten und Gewichtungen zu
RoutingPlan::dispatch(input) Versendet Token durch Experten
SwiGluExperts::new(gate, up, down) Erstellt bias-freie Expertengewichte
SwiGluExperts::forward_dispatched Berechnet versendete Token
DispatchedTokens::combine Stellt die Token-Reihenfolge wieder her und kombiniert gewichtete Ergebnisse
SwiGluExperts::forward(input, logits, options) Führt die komplette lokale Vorwärtssequenz aus

Diese Schnittstellen verwenden RudaTensor<R>. Berechnungseinstiegspunkte geben Result mit MoeError für ungültige Formen, D-Typen oder andere Argumente zurück.

4. Routing-Vertrag

Logits haben die Form [T, E] und verwenden unquantisiertes F32, F16 oder BF16. RoutingOptions enthält top_k: usize und renormalize: bool, wobei 1 ≤ top_k ≤ E gilt.

Softmax berechnet vor der Top-K-Auswahl alle Experten in FP32. Unentschieden begünstigen niedrigere Experten-IDs. Wenn die Renormierung aktiviert ist, werden ausgewählte Gewichtungen neu normalisiert und dann in die Logits dtype umgewandelt. Zeilen, die NaN, positive Unendlichkeit oder nur negative Unendlichkeit enthalten, behalten die Gewichtungen von NaN bei, anstatt eine gleichmäßige Verteilung zu verwenden.

Ausgewählte Expertenindizes und -gewichte haben beide die Form [T, top_k]. Indizes verwenden U32.

5. Expertengewichte und Verteilung

Eingabetokens haben die Form [T, H]; gate und up haben [E, I, H], down hat [E, H, I]. Gewichte müssen denselben Gleitkomma-dtype und dasselbe Gerät verwenden. Expertenanzahl und Dimensionen müssen zu Routing und Eingabe passen.

Die Verteilung verwirft keine Tokens zur Durchsetzung einer Kapazitätsgrenze. Die atomare Zuweisungsreihenfolge innerhalb eines Experten ist nicht festgelegt; eine gespeicherte Zuordnung stellt die Token-Reihenfolge wieder her. Der Vorwärtseinstiegspunkt nimmt vorberechnete Logits entgegen, statt die Gate-Projektion des Modells auszuführen oder Gewichtsdateien zu laden.

Quelle: Routing, Dispatch and Combine, Experten und Tests.

6. MoE aufrufen

Aktivieren Sie tensor-moe für Ihre ruDNN-Abhängigkeit. Bereiten Sie Gerätetensoren mit den oben genannten Layouts vor, erstellen Sie dann Expertengewichte und führen Sie die Vorwärtsoperation aus:

use rudnn::moe::{RoutingOptions, SwiGluExperts};

let experts = SwiGluExperts::new(gate, up, down)?;
let options = RoutingOptions {
    top_k: 2,
    renormalize: true,
};
let output = experts.forward(input, logits, options)?;

Dadurch werden zwei Experten pro Token ausgewählt, daher muss E mindestens 2 sein. input hat die Form [T, H], logits hat die Form [T, E] und output hat die Form [T, H]. Verwenden Sie experts in nachfolgenden Eingabestapeln wieder, ohne das Gewichtsobjekt neu zu erstellen.

Um das Routing zu überprüfen oder Ihre eigene Verarbeitung zwischen den Phasen einzufügen, rufen Sie diese separat auf:

use rudnn::moe::route;

let routing = route(logits, options)?;
let selected_experts = routing.expert_indices();
let selected_weights = routing.weights();
let dispatched = routing.dispatch(input)?;
let expert_output = experts.forward_dispatched(&dispatched)?;
let output = dispatched.combine(expert_output)?;

Dies sind alternative Formen; Die zweite beginnt mit einer neuen Charge input und logits. combine verwendet die Dispatch-Zuordnung, um die Token-Reihenfolge wiederherzustellen und führt Expertenausgaben mithilfe von Routing-Gewichten zusammen.

Form, dtype oder Gerätekonflikte geben MoeError zurück. Um Ergebnisse auf dem Host zu lesen, verwenden Sie ruda_kernel::tensor::readback::into_data_sync(output), das auf Geräteergebnisse wartet und TensorData zurückgibt.

7. LayerNorm, RMSNorm und Softmax

Aktivieren Sie tensor-normalization und importieren Sie diese Funktionen aus rudnn::normalization. Alle arbeiten auf der endgültigen Eingabeachse und behalten die Form bei:

Funktion Eingabe Parameter
layer_norm(input, gamma, beta, epsilon) F32/F16/BF16 F32 Vektor gamma, optionaler F32 Vektor beta
rms_norm(input, gamma, epsilon) F32/F16/BF16 F32 Vektor gamma
softmax_last_axis(input) F32 Keine zusätzlichen Parameter

Die Eingabe muss unquantisiert sein und eine nicht leere Endachse haben. Für die Endachsenlänge H müssen gamma und beta die Form [H] haben, unquantisiert sein und sich das Eingabegerät teilen. epsilon muss endlich und positiv sein. Affine Parameter bleiben auch für BF16/F16-Eingänge F32. Statistik und affine Arithmetik verwenden FP32, wobei die Ausgabe in die Eingabe dtype umgewandelt wird.

use ruda_kernel::{dsl::Runtime, tensor::RudaTensor};
use rudnn::normalization::{NormalizationError, layer_norm, rms_norm, softmax_last_axis};

fn normalize<R: Runtime>(
    input: RudaTensor<R>,
    gamma: RudaTensor<R>,
    beta: Option<RudaTensor<R>>,
    epsilon: f32,
) -> Result<RudaTensor<R>, NormalizationError> {
    layer_norm(input, gamma, beta, epsilon)
}

fn normalize_rms<R: Runtime>(
    input: RudaTensor<R>,
    gamma: RudaTensor<R>,
    epsilon: f32,
) -> Result<RudaTensor<R>, NormalizationError> {
    rms_norm(input, gamma, epsilon)
}

fn probabilities<R: Runtime>(
    logits: RudaTensor<R>,
) -> Result<RudaTensor<R>, NormalizationError> {
    softmax_last_axis(logits)
}

8. Gated-Delta-Prefill und Rekurrenz

Aktivieren Sie tensor-gated-delta. Verwenden Sie chunk_gated_delta_rule(input, chunk_size) für das Vorfüllen von Chunked-Sequenzen und gated_delta_rule(input) für die Token-für-Token-Wiederholung. Beide nehmen GatedDeltaInput<R>:

Feld Form/Typ
query, key [B, H, T, K], passend zu F32/F16/BF16
value [B, H, T, V], gleicher dtype wie Abfrage
beta [B, H, T], gleicher dtype wie Abfrage
log_decay [B, H, T], F32
initial_state [B, H, K, V], F32
query_scale Endlicher f32-Wert gemäß Modellkonfiguration

Alle Tensoren müssen unquantisiert sein und sich auf demselben Gerät befinden. Angebot Q/K nach modellspezifischer Normalisierung; Der Einstiegspunkt übernimmt dies nicht für Sie. Diese Funktion verwendet die vorherigen Runtime- und RudaTensor-Importe wieder:

use rudnn::gated_delta::{
    GatedDeltaError, GatedDeltaInput, GatedDeltaOutput, chunk_gated_delta_rule,
};

fn delta_prefill<R: Runtime>(
    query: RudaTensor<R>,
    key: RudaTensor<R>,
    value: RudaTensor<R>,
    beta: RudaTensor<R>,
    log_decay: RudaTensor<R>,
    initial_state: RudaTensor<R>,
    query_scale: f32,
    chunk_size: usize,
) -> Result<GatedDeltaOutput<R>, GatedDeltaError> {
    chunk_gated_delta_rule(
        GatedDeltaInput {
            query, key, value, beta, log_decay, initial_state, query_scale,
        },
        chunk_size,
    )
}

Das zurückgegebene output hat die Form [B, H, T, V] und denselben dtype wie query. final_state ist F32 mit der Form [B, H, K, V]. Übergeben Sie für den nächsten Abschnitt derselben Sequenz diesen final_state als initial_state. Halten Sie für verschiedene Sequenzen getrennte Zustände vor. Der Anfangszustand wird nicht in-place überschrieben.

chunk_size muss positiv sein. Der dreieckige Arbeitsbereich von 4 × (chunk_size² + chunk_size) Bytes darf das Shared-Memory-Limit des Geräts pro Arbeitsgruppe nicht überschreiten. Der Einstiegspunkt füllt den letzten Chunk auf; das Padding wird aus der Ausgabe ausgeschlossen. Ungültige Argumente liefern GatedDeltaError.

Informationen zu Text- und Bildaufrufen auf Modellebene finden Sie im ruLLM-Inferenzleitfaden.

9. Seitenbasierte Attention und MLA

Aktivieren Sie tensor-paged-attention und verwenden Sie rudnn::paged_attention. HostPlan::new(page_size, pages, tables, lengths, sequence_ids, positions) validiert die Scheduling-Metadaten auf dem Host; positions enthält absolute, bei null beginnende Positionen innerhalb jeder Sequenz. DevicePlan::upload(host, &q) überträgt diese Metadaten auf das Gerät und die Ausführungsqueue der Query. Der Plan darf nur bei unverändertem Schedule wiederverwendet werden.

DevicePlan::attention(q, k, v, scale, causal) liest physische Cache-Seiten direkt für gepacktes Prefill/Decode variabler Länge. Q hat die Form [queries, Hq, D], K [pages, page_size, Hkv, D], V [pages, page_size, Hkv, Dv] und das Ergebnis [queries, Hq, Dv]; Hq muss durch Hkv teilbar sein. Eingaben müssen zusammenhängende, nicht quantisierte F32/F16/BF16-Tensoren mit gleichem dtype, Gerät und gleicher Queue sein. Q/K/V müssen endlich und scale endlich und positiv sein. D und Dv liegen in 1..=1024; das Gerät muss eine Plane mit 32 oder 64 Lanes und das erforderliche Launch-Grid unterstützen. Vorwärtslauf und Rückwärtslauf erster Ordnung sind verfügbar; beliebige externe Masken und quantisierte KV-Caches werden nicht unterstützt.

DevicePlan::mla(q, qp, latent, kp, scale, causal) nimmt Queries mit absorbierter Projektion [queries, H, R], Positionsqueries [queries, H, P], einen gemeinsamen latenten Cache [pages, page_size, 1, R] und einen Positionscache [pages, page_size, 1, P] entgegen. Das Ergebnis ist komprimierter Kontext [queries, H, R]; P liegt in 1..=256. Positionskodierung erfolgt vor dem Aufruf, Value-/Output-Projektionen danach. Verwenden Sie die ursprüngliche QK-Skalierung des Modells, nicht eine aus dem komprimierten Rang abgeleitete Skalierung.

Die obigen Methoden verwenden den ungeteilten Pfad. Zum Aufteilen einer Historie erstellen Sie SplitWorkspace::new(&q, queries, heads, value_dim, splits) mit 2..=32 Splits und rufen attention_with_workspace oder mla_with_workspace auf. Teilstatistiken und Zusammenführung verwenden FP32. Ein Workspace ist auf 64 MiB begrenzt und darf nur bei passender Form in derselben geordneten Ausführungsqueue wiederverwendet werden.

DevicePlan::append(k, v, key_cache, value_cache) liefert die Cache-Tensoren, die für weitere Aufrufe aufzubewahren sind. Gemeinsam genutzte Cache-Allokationen werden vor Änderungen kopiert; gemeinsam genutzte physische Präfixseiten erfordern zusätzlich Copy-on-Write durch den Scheduler. Doppelte Schreibzugriffe auf dieselbe physische Position werden abgewiesen.

10. Gruppenbeschränktes Sigmoid-MoE-Routing

Mit tensor-moe liefert route_sigmoid_grouped(logits, bias, options) einen RoutingPlan. Logits haben die Form [tokens, experts] und den Typ F32/F16/BF16; der optionale Korrektur-Bias ist FP32 [experts] auf demselben Gerät und derselben Queue. Bias beeinflusst nur die Auswahl. Die zurückgegebenen Gewichte verwenden die ursprünglichen Sigmoid-Werte, optionale Renormalisierung und scale; bei Gleichstand werden kleinere IDs bevorzugt.

GroupRoutingOptions enthält top_k, groups, selected_groups, group_top_two, renormalize und scale. Die Expertenzahl liegt in 1..=1024, die Gruppenzahl in 1..=128 und top-k in 1..=64. Die Expertenzahl muss durch die Gruppenzahl teilbar sein, die Zahl ausgewählter Gruppen muss gültig sein und top-k darf deren gesamte Expertenzahl nicht überschreiten. group_top_two=true summiert die beiden größten korrigierten Werte je Gruppe und erfordert mindestens zwei Experten pro Gruppe; andernfalls wird das Maximum verwendet. Scale muss endlich und positiv sein.

SwiGluExperts::forward_sigmoid_grouped(input, logits, bias, options, strategy) führt Routing, Dispatch, Expertenberechnung und Kombination aus. forward_dispatched_with_strategy wählt GroupedStrategy::Scalar, Auto oder TensorCore; die bestehenden Methoden forward und forward_dispatched behalten Scalar bei. Tensor-Core-Ausführung erfordert geeignete F16/BF16-Hardware. Auto fällt nur bei nicht unterstützter Konfiguration zurück, nicht bei Kompilierungs- oder Ausführungsfehlern. Modellprojektionen, gemeinsame Experten und Residualzweige bleiben Aufgabe des Aufrufers.

11. Rückwärtslauf für paged Attention und geordnete Historiengradienten

DevicePlan::attention_backward(q, k, v, grad_out, scale, causal) liefert AttentionBackward { dq, dk, dv }; mla_backward(q, qp, latent, kp, grad_out, scale, causal) liefert MlaBackward { dq, dqp, dlatent, dkp }. dlatent enthält Key- und Value-Beiträge. Wahrscheinlichkeiten werden im Rückwärtslauf neu berechnet, statt eine vollständige Score-Matrix zu speichern.

Die unsicheren APIs attention_backward_selected_into und mla_backward_selected_into akzeptieren unabhängig optionale Gradientenpuffer. None lässt die jeweilige Ausgabe und ihren zweigspezifischen Historienpuffer weg; andere Ableitungen können den Eingang weiterhin benötigen. Ausgaben dürfen weder Eingaben noch einander überlappen. Alle Zugriffe erfolgen auf der geordneten Queue des Plans. Historiengradienten verwenden hier FP32-Atomics und sind nicht bitweise deterministisch.

Für eine Historienreduktion ohne Atomics erstellen Sie OrderedBackwardWorkspace::new(&plan, &q)? und übergeben ihn veränderbar an attention_backward_ordered_into oder mla_backward_ordered_into. Die Überlappungsverbote gelten auch für Workspace-Puffer. Wiederverwendung erfordert kompatible unveränderliche Zeitplanmetadaten, Query-/Head-Anzahl, Gerät und Queue. Statistik und inverse Metadaten teilen ein Budget von 64 MiB. Eine feste Summationsreihenfolge garantiert keine Bitgleichheit zwischen Geräten oder mit dem atomaren Pfad.

Workspace-Option Standard Wirkung
set_query_pruning(bool) true Überspringt nachweislich kausal unsichtbare Queries, ohne die übrige Summationsreihenfolge zu ändern.
set_history_row_cache(bool) false Nutzt Historienzeilen threadlokal wieder; kein zusätzlicher Gerätetensor, aber möglicherweise höherer Registerdruck.
set_history_compaction(bool)? false Berechnet Historiengradienten nur für aktive physische Seiten und schreibt inaktive Seiten explizit mit Null.

RUDA_PAGED_ORDERED_CACHE_ROWS=1 und RUDA_PAGED_ORDERED_COMPACT_HISTORY=1 aktivieren die letzten beiden Optionen beim Erstellen des Workspace. Nicht gesetzt oder 0 deaktiviert sie; andere Werte sind Fehler. Änderungen der Umgebung ändern bestehende Workspaces nicht.

Aktive Seiten sind über effektive KV-Längen von Sequenzen mit Queries erreichbar; Tabellenkapazität oder die Anzahl von Nichtnullgradienten sind nicht maßgeblich. Erstmaliges Aktivieren lädt einen Index von physical_pages * 4 Bytes innerhalb desselben Budgets hoch. Späteres Umschalten verwendet ihn erneut; Deaktivieren behält den Speicher. history_compaction_pages() liefert Option<(active_pages, inactive_pages)>, bytes() zählt behaltenen Speicher mit. Budgetfehler lassen den bisherigen Modus unverändert. Der atomare PyTorch-Standard bleibt erhalten; eine Beschleunigung ist nicht garantiert.

12. MoE-Training erster Ordnung

selected_router_weights(&logits, &indices, options) liefert FP32-Gewichte [T, top_k]; selected_router_backward(&logits, &indices, &grad_weights, options) liefert [T, E]-Gradienten im Logits-dtype. Logits sind zusammenhängende F32/F16/BF16-Tensoren, Indizes zusammenhängend in U32/I32/I64; es gilt 1 <= top_k <= min(E, 64) auf demselben Gerät und derselben Queue. RouterWeightOptions wählt RouterScoring::Softmax oder Sigmoid, optionale Renormalisierung ausgewählter Gewichte und anschließend einen endlichen positiven scale. grad_weights ist FP32.

Wiederholte Indizes haben Gather-Semantik. Ungültige Indizes erzeugen NaN für die ganze Zeile ohne ungültigen Speicherzugriff oder Host-Synchronisierung. Differenziert werden kontinuierliche Gewichte einer festen Auswahl, nicht Top-k-/Gruppenentscheidungen oder Korrektur-Bias. RoutingPlan::into_training(logits, options) behält die Auswahl und berechnet Gewichte neu. Verwenden Sie RouterTrainingPlan::routing() zur Verteilung und backward(&grad_weights) für Logits-Gradienten. Gespeicherte Eingaben müssen unverändert bleiben.

Behalten Sie output und cache aus SwiGluExperts::forward_dispatched_training(&dispatched, strategy). Die Rückwärtskette ist:

  1. dispatched.combine_backward(&expert_output, grad_output) liefert dexpert und FP32-dweights.
  2. cache.backward(dexpert) liefert dinput für verteilte Zeilen sowie FP32-dgate, dup, ddown.
  3. dispatched.dispatch_backward(dinput) summiert ausgewählte Zeilen zum ursprünglichen Token, ohne Routinggewichte erneut anzuwenden.
  4. Router-Backward erhält dweights und liefert Logits-Gradienten.

combine_backward verwendet standardmäßig CombineGradientStrategy::Serial; combine_backward_with_strategy erlaubt Plane. Experten-backward ist unabhängig von der Vorwärtsstrategie standardmäßig skalar; backward_with_strategy akzeptiert GroupedStrategy::Scalar, Auto oder TensorCore. Tensor Core benötigt unterstützte F16/BF16-Hardware. Auto fällt nur bei fehlenden Fähigkeiten zurück, nicht bei Kompilierungs- oder Ausführungsfehlern.