Go · Runtime Dispatch

Runtime Dispatch

import "github.com/ashvardanian/NumKong" 8.0.0-rc.1 · b1f866ab

A Device is the host CPU, from CPU(), or a GPU by its runtime’s own ordinal, from NewDevice(DeviceCUDA, 0) and its DeviceROCm and DeviceMetal twins, counted by CountDevices. Device.ConfigureThread pins the current goroutine to an OS thread via runtime.LockOSThread, enables the CPU-specific state the given capabilities need, such as Intel AMX tiles, then returns an unlock function. Goroutines can migrate between OS threads, so thread-local state (AMX tiles) would be lost without pinning.

cpu := nk.CPU()
enabled, _ := cpu.CapabilitiesEnabled() // what dispatch runs within: detected on this CPU and compiled in
unlock, _ := cpu.ConfigureThread(enabled) // lock thread, configure what dispatch uses
defer unlock()                            // release the OS thread on return

fmt.Println(enabled)                 // like "serial,neon,neonhalf,neonfhm,neonsdot"
fmt.Println(enabled.Has(nk.CapNEON)) // test one capability

if gpu, err := nk.NewDevice(nk.DeviceMetal, 0); err == nil {
	fmt.Println(gpu.CapabilitiesEnabled()) // like "metal,apple9"
}

CapabilitiesDetected and CapabilitiesCompiled report the two raw axes, what the device executes and what this binary contains for its kind. Every kernel call passes CapCPUs, which the library clamps to the CPU’s CapabilitiesEnabled, settled as it loads, so the package keeps no mask of its own. Every capability is a typed Capability constant, like CapSerial, CapNEON, CapHaswell, CapSapphireAMX, CapSME, CapAmpere, and CapApple9, and CapCPUs, CapGPUs, and CapAny group them. These are useful for logging the active platform or gating optional benchmark paths.

API

Types

DeviceKindDeviceKind is the runtime a device belongs to, as the nk_<kind>_\* C functions name it.
capabilities.go:78 ↗
type DeviceKind int

Values

DeviceCPUiota
DeviceCUDA
DeviceROCm
DeviceMetal
EnumCapabilityCapability is one capability of a CPU or a GPU, or a set of them.2
capabilities.go:17 ↗
type Capability uint64

Values

CapSerialAlways: Fallback
CapNEON2013: ARM NEON
CapNEONHalf2017: ARM NEON FP16
CapNEONBFDot2020: ARM NEON BF16
CapNEONFHM2018: ARM NEON FP16 FML
CapNEONSDot2017: ARM NEON i8 dot
CapNEONFP8ARM NEON FP8
CapSVE2020: ARM SVE
CapSVEHalf2020: ARM SVE FP16
CapSVESDot2020: ARM SVE i8 dot
CapSVEBFDot2021: ARM SVE BF16
CapSVE22022: ARM SVE2
CapSME2024: ARM SME
CapSMEF642024: ARM SME F64
CapSMEBi322025+: ARM SME BI32I32
CapHaswell2013: Intel AVX2
CapAlder2021: Intel AVX2+VNNI
CapSierra2024: Intel AVXVNNIINT8
CapSkylake2017: Intel AVX-512
CapIceLake2019: Intel AVX-512 VNNI
CapGenoa2020: AMD AVX-512 BF16
CapTurin2024: AMD Turin AVX-512 CD
CapSapphire2023: Intel AVX-512 FP16
CapDiamond2025+: Intel AVX10.2
CapSapphireAMX2023: Intel Sapphire AMX
CapGraniteAMX2024: Intel Granite AMX FP16
CapDiamondAMXIntel Diamond Rapids AMX
CapRVV2023: RISC-V Vector
CapRVVBF162023: RISC-V Zvfbfwma
CapRVVHalf2023: RISC-V Zvfh
CapRVVBBRISC-V: Byte-Byte extensions
CapV1282021: WASM SIMD128
CapV128Relaxed2022: WASM Relaxed SIMD
CapPowerVSXPower VSX 128-bit SIMD
CapLoongsonASXLoongArch LASX 256-bit SIMD
CapCUDAAny CUDA device
CapAmpere2020: NVIDIA SM 8.0
CapAda2022: NVIDIA SM 8.9
CapHopper2022: NVIDIA SM 9.x
CapBlackwell2024: NVIDIA SM 10.x
CapBlackwellRTX2025: NVIDIA SM 12.x
CapBlackwellUltra2025: NVIDIA SM 10.3
CapROCmAny ROCm device
CapCDNA32023: AMD gfx942
CapCDNA42025: AMD gfx950
CapCDNA5AMD gfx1250
CapMetalAny Metal device
CapApple92023: Apple GPU family 9
CapApple10Apple GPU family 10
CapCPUsEvery CPU capability, which every kernel call passes
CapGPUsEvery GPU capability
CapAny^Capability(0)Every capability
HasHas reports whether any bit of capability is in c.
capabilities.go:213 ↗
func (c Capability) Has(capability Capability) bool
StringString names the capabilities in c, comma-separated, like "serial,haswell".
capabilities.go:216 ↗
func (c Capability) String() string
StructDeviceDevice is one device NumKong can run kernels on: the host CPU, or a GPU by its runtime's own ordinal, the one cudaSetDevice or hipSetDevice takes, or the position in Metal's device list.6
capabilities.go:90 ↗
type Device struct {
    Kind    DeviceKind
    Ordinal int
}
CPUCPU returns the host CPU, which every build has.
capabilities.go:96 ↗
func CPU() Device
NewDeviceNewDevice returns device ordinal of kind, failing past the last one.
capabilities.go:118 ↗
func NewDevice(kind DeviceKind, ordinal int) (Device, error)
CapabilitiesCompiledCapabilitiesCompiled returns the capabilities whose kernels were compiled in for devices of d's kind, whether or not d runs them.
capabilities.go:148 ↗
func (d Device) CapabilitiesCompiled() Capability
CapabilitiesDetectedCapabilitiesDetected returns the capabilities d runs, whether or not they were compiled in.
capabilities.go:127 ↗
func (d Device) CapabilitiesDetected() (Capability, error)
CapabilitiesEnabledCapabilitiesEnabled returns the mask d's kernel calls run within: Device.CapabilitiesDetected and Device.CapabilitiesCompiled at once.
capabilities.go:166 ↗
func (d Device) CapabilitiesEnabled() (Capability, error)

On the CPU the library settles it as it loads, it always has CapSerial, and every kernel call of this package passes CapCPUs clamped to it.

ConfigureThreadConfigureThread pins the goroutine to an OS thread, configures its SIMD state for capabilities, usually the CPU's Device.CapabilitiesEnabled, and returns the unlock function.
capabilities.go:188 ↗
func (d Device) ConfigureThread(
    capabilities Capability,
) (func(), error)

Call it, typically via defer, once the SIMD work is done. GPUs have no thread state to configure.

Functions

CountDevicesCountDevices returns how many devices of kind the process sees: one CPU, or the GPUs its runtime counts, failing without one.
numkong.go:100 ↗
func CountDevices(kind DeviceKind) (int, error)