web: hand the upscaler's activations to the chip that is running them
The WebGPU execution provider has no PReLU kernel. The model is 34 convolutions with a PReLU after every one of them, so an export that took the GPU path was split 33 times: each activation came off the chip to be activated on the processor and went straight back, a 64-channel map in both directions, per tile. A machine with a good graphics chip was not exporting any faster for having it. PReLU(x) is exactly Relu(x) - slope * Relu(-x), and Relu, Neg, Mul and Sub the provider does implement, so scripts/realesr-gpu.py writes the 33 activations out as those four and drops the slopes nobody reads any more. The model file is the output of that script, not the file as published. One 256x256 tile through the model before and after, on a WebGPU session: the runtime no longer reports nodes left off the preferred provider (it did, once, before) and the processor path answers bit for bit what it answered before. The warning itself cannot be switched off from here - env.logLevel is read when the runtime module initialises, before any of this runs - so the graph was fixed rather than the lines hidden.
This commit is contained in:
@@ -9,6 +9,11 @@ import type * as Ort from 'onnxruntime-web';
|
||||
// Both the runtime (served next to canvaskit.wasm, see scripts/copy-wasm.mjs)
|
||||
// and the model (public/models) are static files; nothing here changes what the
|
||||
// server can do.
|
||||
//
|
||||
// The model is not the file as published: its 33 PReLU activations are written
|
||||
// out as Relu/Neg/Mul/Sub, because the WebGPU provider has no PReLU kernel and
|
||||
// would otherwise hand every activation to the processor and take it back, 33
|
||||
// times per tile. scripts/realesr-gpu.py is that rewrite and explains it.
|
||||
|
||||
const MODEL_URL = '/models/realesr-general-x4v3.onnx';
|
||||
// The wasm dir, not the file: the runtime picks its own name inside it.
|
||||
@@ -54,6 +59,10 @@ function load(): Promise<Loaded> {
|
||||
// A laptop with two GPUs would otherwise hand this to the one built into
|
||||
// the processor. The model is the export, so ask for the fast one.
|
||||
ort.env.webgpu.powerPreference = 'high-performance';
|
||||
// env.logLevel looks like a switch for the runtime's own warnings and is not
|
||||
// one — it is read when the module initialises, before this runs, so a level
|
||||
// set here silences nothing. Left alone, they are worth reading: the last one
|
||||
// to appear said the graph was being split between the chip and the processor.
|
||||
const session = await ort.InferenceSession.create(MODEL_URL, { executionProviders: ['webgpu'] }).catch(() =>
|
||||
ort.InferenceSession.create(MODEL_URL, { executionProviders: ['wasm'] })
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user