XI · Hexagon NPU (welvet.qnn) / CHAPTER 76
QNN: go_v_qnn RESULTS (large shapes)
github.com/openfluke/w2a/suites/go_v_qnn✅ matrix published
Why it exists
Toy shapes lie. The w2a large matrix (dense 32×512×512, softmax 64×4096, …) is the honest Snapdragon X story: NPU DLL graphExecute vs Go/native f32 CPU, plus Go→NPU call overhead (cgo + pack + online compose).
What it is
Published tables in w2a/suites/go_v_qnn/RESULTS.md. Dense prepare-once wins ~93-98% vs Go/native. Softmax/norms/CNN/SwiGLU/MHA win on DLL exec; online layers pay compose cost on the call timer. LSTM large FAIL. Host compares f32 only: dtype matrix is NPU-side.
How to read the timers
- NPU DLL exec: mono inside welvet.qnn around
graphExecuteonly. - Go→NPU call: full C ABI from Go (cgo + pack/unpack + online create/finalize).
- Dense = prepare-once + warmed execute; other layers = online compose today.
- % =
(slower−faster)/slower×100vs that host column.
Headline NPU wins (DLL exec vs Go f32)
| Layer | dtype | Go | NPU | vs Go |
|---|---|---|---|---|
| dense | u8 | 3.05ms | 164µs | NPU 95% |
| dense | f32 | 3.05ms | 201µs | NPU 93% |
| softmax | f16 | 4.31ms | 446µs | NPU 90% |
| rmsnorm | u8 | 9.40ms | 897µs | NPU 90% |
| layernorm | f16 | 6.82ms | 553µs | NPU 92% |
| cnn2 | i8 | 12.56ms | 763µs | NPU 94% |
| swiglu | u16 | 1.92ms | 352µs | NPU 82% |
| mha | f16 | 4.51ms | 372µs | NPU 92% |
Full status / call overhead / NPU-wins-only tables:
RESULTS.md.
Re-run: cd w2a && go test ./tests/go_v_qnn -v -count=1 -run TestGoVQNNMatrix -timeout 180m.
Failures today: lstm float32/float16: code=2 execute on large shapes.
Go example
examples/81-qnn-results/main.go
cd welvet/examples/81-qnn-results && source ../env.sh && go run .package main
import "fmt"
// Snapshot of w2a/suites/go_v_qnn/RESULTS.md (2026-10-23, Snapdragon X).
// This example is host-only: no DLL required.
func main() {
fmt.Println("welvet.qnn 1.0.0 · go_v_qnn large matrix")
fmt.Println("host: Windows ARM64 · shapes: dense 32x512x512 …")
fmt.Println()
fmt.Println("NPU DLL wins (subset vs Go f32):")
rows := []struct{ layer, dt, goT, npu, pct string }{
{"dense", "u8", "3.05ms", "164µs", "95%"},
{"dense", "f32", "3.05ms", "201µs", "93%"},
{"softmax", "f16", "4.31ms", "446µs", "90%"},
{"rmsnorm", "u8", "9.40ms", "897µs", "90%"},
{"layernorm", "f16", "6.82ms", "553µs", "92%"},
{"cnn2", "i8", "12.56ms", "763µs", "94%"},
{"swiglu", "u16", "1.92ms", "352µs", "82%"},
{"mha", "f16", "4.51ms", "372µs", "92%"},
}
for _, r := range rows {
fmt.Printf(" %-10s %-4s Go %s NPU %s → %s\n", r.layer, r.dt, r.goT, r.npu, r.pct)
}
fmt.Println()
fmt.Println("note: call timer ≫ DLL exec on online layers (compose each call)")
fmt.Println("fail: lstm f32/f16 execute code=2")
fmt.Println("full: w2a/suites/go_v_qnn/RESULTS.md")
}
Output
welvet.qnn 1.0.0 · go_v_qnn large matrix
host: Windows ARM64 · shapes: dense 32x512x512 …
NPU DLL wins (subset vs Go f32):
dense u8 Go 3.05ms NPU 164µs → 95%
dense f32 Go 3.05ms NPU 201µs → 93%
softmax f16 Go 4.31ms NPU 446µs → 90%
rmsnorm u8 Go 9.40ms NPU 897µs → 90%
layernorm f16 Go 6.82ms NPU 553µs → 92%
cnn2 i8 Go 12.56ms NPU 763µs → 94%
swiglu u16 Go 1.92ms NPU 352µs → 82%
mha f16 Go 4.51ms NPU 372µs → 92%
note: call timer ≫ DLL exec on online layers (compose each call)
fail: lstm f32/f16 execute code=2
full: w2a/suites/go_v_qnn/RESULTS.md
Validate (harness)
cd welvet/examples/81-qnn-results && source ../env.sh && go run .