XV · Vulkan acceleration (welvet.vulkan) / CHAPTER 14
Vulkan: mount and forward
github.com/openfluke/welvet/nativevulkanlinux amd64
Why it exists
Run a Go layer on a Vulkan GPU with an explicit lifetime via the independent welvet.vulkan library.
What it is
Mount an identity Dense layer, inspect the Vulkan version and device identity, and forward a Float32 tensor.
Session ownership
Create a session with nativevulkan.Mount, call Forward repeatedly and close it when finished. Mount accepts supported layers, Stack, Parallel and Grid layouts. The library is independent of welvet.cpp, welvet.metal, welvet.cuda and welvet.rocm.
Requirements and backend boundaries
Go Welvet v1.6.0 adds the independent welvet.vulkan 0.79 library (mounted model ABI 1) at github.com/openfluke/welvet.vulkan. Install from its checkout:
cd ../welvet.vulkan
./scripts/linux_install_go.sh
Execution requires Linux x86_64, Go with cgo, and a Vulkan 1.x-capable device + loader/runtime. Set WELVET_VULKAN_LIBRARY to override library discovery. Ordinary Go CPU use does not require a Vulkan GPU. Unsupported hosts print SKIP; missing libraries or no GPU on a supported host also soft-SKIP in these book examples.
Honest coverage: no silent host fallback labeled as Vulkan (see sibling docs/VULKAN_ONLY.md). LSTM/RNN/Mamba/GDN gates still use host exp/tanh after GPU MatVec: same pattern as cuda. Windows artifacts are not shipped yet.
Go schedules work and manages memory; numerical Vulkan forward, backward and weight updates execute SPIR-V compute when a device is present. Activations are Float32; FormatNone parameter storage follows the Vulkan dtype matrix. Small examples demonstrate APIs; GPU launch costs can outweigh useful work at small shapes.
cpu-tiled / go_cpu means Go CPU; native_cpu means welvet.cpp; vulkan means the independent Vulkan GPU library. Examples 103-106 can use go run -tags welvet_vulkan . to exclude C++ linkage. Chapter 108 requires the normal cgo build for both native engines. JSON routing (§107-§108) is Linux amd64.
Go example
examples/103-vulkan-mount/main.go
cd welvet/examples/103-vulkan-mount && source ../env.sh && go run .// Mount one layer, execute its forward pass on Vulkan, and release it.
package main
import (
"flag"
"fmt"
"log"
"runtime"
"github.com/openfluke/welvet/core"
"github.com/openfluke/welvet/layers/dense"
"github.com/openfluke/welvet/nativevulkan"
"github.com/openfluke/welvet/quant"
)
func main() {
if e := run(); e != nil {
log.Fatal(e)
}
}
func run() error {
library := flag.String("library", "", "optional libwelvet_vulkan.so/.dll path")
flag.Parse()
if !vulkanPlatformOK() {
fmt.Println("SKIP: Vulkan needs linux/amd64 and cgo")
return nil
}
l, e := dense.NewConfigured(2, 2, core.ActivationLinear, core.DTypeFloat32, quant.FormatNone, []float32{1, 0, 0, 1})
if e != nil {
return e
}
session, e := nativevulkan.Mount(l, nativevulkan.Options{LibraryPath: *library})
if e != nil {
fmt.Printf("SKIP: Vulkan unavailable (%v)\n", e)
return nil
}
defer session.Close()
x := &core.Tensor[float32]{Shape: []int{1, 2}, Data: []float32{.5, -.25}}
post, e := session.Forward(x)
if e != nil {
return e
}
fmt.Printf("backend=vulkan version=%s\ndevice=%s\ninput=%v output=%v shape=%v\n", session.Version(), session.Identity(), x.Data, post.Data, post.Shape)
return nil
}
func vulkanPlatformOK() bool {
return runtime.GOOS == "linux" && runtime.GOARCH == "amd64"
}
Output
backend=vulkan version=0.79
device=vulkan:llvmpipe (LLVM 22.1.8, 256 bits):idx=0:api=1.4.354:type=4:mem=33412538368:f64=1
input=[0.5 -0.25] output=[0.5 -0.25] shape=[1 2]
Authorization required, but no authorization protocol specified
Authorization required, but no authorization protocol specified
Validate (harness)
cd welvet/examples/103-vulkan-mount && source ../env.sh && go run .