Verwendung des WebGPU Execution Providers
Dieses Dokument erklärt, wie der WebGPU Execution Provider in ONNX Runtime verwendet wird.
Inhalt
Grundlagen
Was ist WebGPU? Sollte ich es verwenden?
WebGPU ist ein neuer Webstandard für allgemeine GPU-Berechnungen und Grafiken. Er ist als Low-Level-API konzipiert, basierend auf D3D12, Vulkan und Metal, und für die Verwendung im Browser gedacht. Er ist effizienter und leistungsfähiger als WebGL und für maschinelles Lernen, Grafiken und andere Rechenaufgaben konzipiert.
WebGPU ist in den neuesten Versionen von Chrome und Edge unter Windows, macOS, Android und ChromeOS sofort verfügbar. Es ist auch in Firefox hinter einem Flag und in Safari Technology Preview verfügbar. Weitere Informationen finden Sie unter WebGPU-Status.
Wenn Sie ONNX Runtime Web für die Inferenz sehr leichter Modelle in Ihrer Webanwendung verwenden und eine kleine Binärgröße wünschen, können Sie weiterhin den standardmäßigen WebAssembly (WASM) Execution Provider verwenden. Wenn Sie rechenintensivere Modelle ausführen möchten oder die GPU des Client-Geräts nutzen möchten, können Sie den WebGPU Execution Provider verwenden.
Wie verwende ich den WebGPU EP in ONNX Runtime Web
Dieser Abschnitt geht davon aus, dass Sie Ihre Webanwendung bereits mit ONNX Runtime Web eingerichtet haben. Wenn nicht, können Sie die Erste Schritte für grundlegende Informationen befolgen.
Um den WebGPU EP zu verwenden, müssen Sie nur 2 kleine Änderungen vornehmen
-
Aktualisieren Sie Ihre Importanweisung
- Ändern Sie für das HTML-Skript-Tag
ort.min.jsinort.webgpu.min.js<script src="https://example.com/path/ort.webgpu.min.js"></script> - Ändern Sie für die JavaScript-Importanweisung
onnxruntime-webinonnxruntime-web/webgpuimport * as ort from 'onnxruntime-web/webgpu';
Weitere Informationen finden Sie unter Bedingtes Importieren.
- Ändern Sie für das HTML-Skript-Tag
-
Geben Sie den 'webgpu' EP explizit in den Sitzungsoptionen an
const session = await ort.InferenceSession.create(modelPath, { ..., executionProviders: ['webgpu'] });
Sie können auch erwägen, die neueste Nightly Build-Version von ONNX Runtime Web (onnxruntime-web@dev) zu installieren, um von den neuesten Funktionen und Verbesserungen zu profitieren.
WebGPU EP-Funktionen
ONNX Runtime Web bietet die folgenden Funktionen, die bei der Verwendung mit dem WebGPU EP hilfreich sein können
Graph-Erfassung
Sie können die Graph-Erfassungsfunktion ausprobieren, wenn Ihr Modell statische Formen hat und alle seine Berechnungskernels auf dem WebGPU EP laufen. Diese Funktion kann potenziell die Leistung Ihres Modells verbessern.
Weitere Informationen finden Sie unter Graph-Erfassung.
Verwendung von ort.env.webgpu Flags
Weitere Informationen finden Sie unter env.webgpu.
Tensor-Daten auf der GPU belassen (IO-Binding)
Standardmäßig sind die Ein- und Ausgaben eines Modells Tensoren, die Daten im CPU-Speicher enthalten. Wenn Sie eine Sitzung mit dem WebGPU EP ausführen, werden die Daten in den GPU-Speicher kopiert und die Ergebnisse zurück in den CPU-Speicher kopiert. Wenn Sie Ihre Eingabedaten von einer GPU-basierten Quelle erhalten oder die Ausgabedaten für die weitere Verarbeitung auf der GPU belassen möchten, können Sie IO-Binding verwenden, um die Daten auf der GPU zu belassen. Dies ist besonders hilfreich, wenn Sie Transformer-basierte Modelle ausführen, die normalerweise ein einzelnes Modell mehrmals mit der vorherigen Ausgabe als nächste Eingabe ausführen.
Für Modelleingaben, wenn Ihre Eingabedaten ein WebGPU-Speicherpuffer sind, können Sie einen GPU-Tensor erstellen und ihn als Eingabetensor verwenden.
Für Modellausgaben gibt es 2 Möglichkeiten, die IO-Binding-Funktion zu nutzen
Bitte überprüfen Sie auch die folgenden Themen
Eingabetensor aus einem GPU-Puffer erstellen
Wenn Ihre Eingabedaten ein WebGPU-Speicherpuffer sind, können Sie einen GPU-Tensor erstellen und ihn als Eingabetensor verwenden
const inputTensor = ort.Tensor.fromGpuBuffer(inputGpuBuffer, {
dataType: 'float32',
dims: [1, 3, 224, 224]
});
Verwenden Sie diesen Tensor als Modelleingaben (Feeds), sodass die Eingabedaten auf der GPU verbleiben.
Vorkonfigurierte GPU-Tensoren verwenden
Wenn Sie die Ausgabeform im Voraus kennen, können Sie einen GPU-Tensor erstellen und ihn als Ausgabetensor verwenden
// Create a pre-allocated buffer and the corresponding tensor. Assuming that the output shape is [10, 1000].
const bufferSize = (10 * 1000) /* number of elements */ * 4 /* bytes per element */;
const device = ort.env.webgpu.device;
const myPreAllocatedBuffer = device.createBuffer({
usage: GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST | GPUBufferUsage.STORAGE,
size: Math.ceil(bufferSize / 16) * 16 /* align to 16 bytes */
});
const myPreAllocatedOutputTensor = ort.Tensor.fromGpuBuffer(myPreAllocatedBuffer, {
dataType: 'float32',
dims: [10, 1000]
});
// ...
// Run the session with fetches
const feeds = { 'input_0': myInputTensor };
const fetches = { 'output_0': myPreAllocatedOutputTensor };
const results = await mySession.run(feeds, fetches);
Durch Angabe des Ausgabetensors in den Fetches verwendet ONNX Runtime Web den vorkonfigurierten Puffer als Ausgabepuffer. Bei einer Forminkongruenz schlägt der run()-Aufruf fehl.
Speicherort der Ausgabedaten angeben
Wenn Sie keine vorkonfigurierten GPU-Tensoren für Ausgaben verwenden möchten, können Sie den Speicherort der Ausgabedaten auch in den Sitzungsoptionen angeben
const mySessionOptions1 = {
...,
// keep all output data on GPU
preferredOutputLocation: 'gpu-buffer'
};
const mySessionOptions2 = {
...,
// alternatively, you can specify the output location for each output tensor
preferredOutputLocation: {
'output_0': 'cpu', // keep output_0 on CPU. This is the default behavior.
'output_1': 'gpu-buffer' // keep output_1 on GPU buffer
}
};
Durch Angabe der Konfiguration preferredOutputLocation behält ONNX Runtime Web die Ausgabedaten auf dem angegebenen Gerät.
Weitere Informationen finden Sie in der API-Referenz: preferredOutputLocation.
Hinweise
Null-dimensionale Tensoren
Wenn die Form eines Tensors eine oder mehrere Dimensionen mit der Größe 0 enthält, gilt der Tensor als null-dimensionaler Tensor. Null-dimensionale Tensoren enthalten keine Daten, daher wird der Speicherort der Daten nicht angewendet. ONNX Runtime Web behandelt null-dimensionale Tensoren immer als CPU-Tensoren. Um einen null-dimensionalen Tensor zu erstellen, können Sie den folgenden Code verwenden
const zeroSizedTensor = new ort.Tensor('float32', [], [3, 256, 0, 64]);
Verwaltung des Lebenszyklus von GPU-Tensoren
Es ist wichtig zu verstehen, wie der zugrunde liegende GPU-Puffer verwaltet wird, um Speicherlecks zu vermeiden und die Effizienz der Buffernutzung zu verbessern.
Ein GPU-Tensor wird entweder vom Benutzercode oder von ONNX Runtime Web als Modellausgabe erstellt.
-
Wenn er vom Benutzercode erstellt wird, wird er immer mit einem vorhandenen GPU-Puffer unter Verwendung von
Tensor.fromGpuBuffer()erstellt. In diesem Fall "besitzt" der Tensor den GPU-Puffer nicht.- Es liegt in der Verantwortung des Benutzers sicherzustellen, dass der zugrunde liegende Puffer während der Inferenz gültig ist, und
buffer.destroy()aufzurufen, um den Puffer zu entsorgen, wenn er nicht mehr benötigt wird. - Vermeiden Sie das Aufrufen von
tensor.getData()undtensor.dispose(). Verwenden Sie den GPU-Puffer direkt. - Die Verwendung eines GPU-Tensors mit einem zerstörten GPU-Puffer führt dazu, dass die Sitzung fehlschlägt.
- Es liegt in der Verantwortung des Benutzers sicherzustellen, dass der zugrunde liegende Puffer während der Inferenz gültig ist, und
-
Wenn er von ONNX Runtime Web als Modellausgabe erstellt wird (kein vorkonfigurierter GPU-Tensor), "besitzt" der Tensor den Puffer.
- Sie müssen sich keine Sorgen machen, dass der Puffer zerstört wird, bevor der Tensor verwendet wird.
- Rufen Sie
tensor.getData()auf, um die Daten vom GPU-Puffer auf die CPU herunterzuladen und die Daten als typisiertes Array zu erhalten. - Rufen Sie explizit
tensor.dispose()auf, um den zugrunde liegenden GPU-Puffer zu zerstören, wenn er nicht mehr benötigt wird.