Book contents +

XV · Vulkan acceleration (welvet.vulkan) / CHAPTER 14

Vulkan: mount and forward

Samuel Watson · Welvet feature bookOriginal source ↗

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

Run: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

exit 0 · last run via go run .

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 .