mat

package
v0.0.6 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 14, 2026 License: MIT Imports: 16 Imported by: 0

Documentation

Overview

Package mat provides WebGPU-buffer-backed 2D matrix operations for Go.

It uses WebGPU (via github.com/gogpu/wgpu) for matrix storage. MatMul, Add, Mul, Scale, Transp, ReduceSum, ReduceSumTo, BroadcastTo, and ReshapeTo execute as WGSL compute kernels when a GPU is available; they fall back to pure Go on a CPU adapter. ReduceMax, Softmax, and RMSNorm use a host compatibility path. All matrices store float32 values in row-major order: element (r, c) is at index r*m.Cols()+c.

Matrix shapes are fixed at construction time. Every operation requires all operands to belong to the same Context, and the output must not alias an input. Add and Mul support 2D singleton-axis broadcasting. Context.Stats can be used to observe host-transfer counts and bytes, compute and readback submissions, and Matrix buffer lifetime. Validation and lifecycle failures can be classified with errors.Is and the exported Err* sentinel errors.

Both CGO modes are supported. Use CGO_ENABLED=0 when a C toolchain is not available, or CGO_ENABLED=1 when combining mat with CGO dependencies:

CGO_ENABLED=0 go build ./...
CGO_ENABLED=1 go build ./...

Import path:

github.com/KEINOS/go-wgpu-mat/mat

Backends are registered internally. Use NewContext to select the execution mode. Without arguments UseAuto is selected by default:

ctx, _ := mat.NewContext()           // UseAuto — try GPU, then CPU
ctx, _ := mat.NewContext(mat.UseGPU) // high-performance GPU adapter
ctx, _ := mat.NewContext(mat.UseCPU) // software/fallback adapter
Example

Example demonstrates the same workflow as the README quickstart with the deterministic CPU adapter so its output can be tested on any machine.

package main

import (
	"fmt"

	"github.com/KEINOS/go-wgpu-mat/mat"
)

func main() {
	panicOnErr := func(err error) {
		if err != nil {
			panic(err)
		}
	}

	// Examples use the deterministic CPU backend. Applications normally use
	// NewContext() (UseAuto) to prefer a GPU and fall back to CPU.
	ctx, err := mat.NewContext(mat.UseCPU)
	panicOnErr(err)

	defer ctx.Release()

	// 2×2 matrices stored in WGPU buffers
	a, err := mat.NewMatrix(ctx, 2, 2)
	panicOnErr(err)

	b, err := mat.NewMatrix(ctx, 2, 2)
	panicOnErr(err)

	c, err := mat.NewMatrix(ctx, 2, 2)
	panicOnErr(err)

	defer a.Release()
	defer b.Release()
	defer c.Release()

	// Upload data (row-major order)
	err = a.Write([]float32{1, 2, 3, 4}) // [[1,2],[3,4]]
	panicOnErr(err)
	err = b.Write([]float32{5, 6, 7, 8}) // [[5,6],[7,8]]
	panicOnErr(err)

	// Compute C = A × B
	err = mat.MatMul(a, b, c)
	panicOnErr(err)

	// Read result back to CPU
	data, err := c.Read()
	panicOnErr(err)

	fmt.Println(data)
}
Output:
[19 22 43 50]
Example (BatchedMatrixMultiplication)

Example_batchedMatrixMultiplication shows that one matrix multiplication evaluates the same linear layer for every sample in a batch.

package main

import (
	"fmt"

	"github.com/KEINOS/go-wgpu-mat/mat"
)

func main() {
	must := func(err error) {
		if err != nil {
			panic(err)
		}
	}

	ctx, err := mat.NewContext(mat.UseCPU)
	must(err)

	defer ctx.Release()

	matrices := make([]*mat.Matrix, 0, 5)
	newMatrix := func(rows, cols int, data []float32) *mat.Matrix {
		matrix, err := mat.NewMatrix(ctx, rows, cols)
		must(err)

		matrices = append(matrices, matrix)

		if data != nil {
			must(matrix.Write(data))
		}

		return matrix
	}

	defer func() {
		for _, matrix := range matrices {
			matrix.Release()
		}
	}()

	// Each row is one sample. All three samples pass through the same weights and bias.
	inputs := newMatrix(3, 2, []float32{
		1, 2,
		3, 4,
		5, 6,
	})
	weights := newMatrix(2, 2, []float32{
		0.5, -0.25,
		0.25, 0.75,
	})
	bias := newMatrix(1, 2, []float32{0.1, -0.2})
	logits := newMatrix(3, 2, nil)
	predictions := newMatrix(3, 2, nil)

	must(mat.MatMul(inputs, weights, logits))
	must(mat.Add(logits, bias, predictions)) // The 1×2 bias broadcasts to all three rows.

	values, err := predictions.Read()
	must(err)

	fmt.Printf("sample 1: [%.2f %.2f]\n", values[0], values[1])
	fmt.Printf("sample 2: [%.2f %.2f]\n", values[2], values[3])
	fmt.Printf("sample 3: [%.2f %.2f]\n", values[4], values[5])
}
Output:
sample 1: [1.10 1.05]
sample 2: [2.60 2.05]
sample 3: [4.10 3.05]
Example (LinearLayerBackwardPropagation)

Example_linearLayerBackwardPropagation shows the three matrix gradients produced by a linear layer during backward propagation.

package main

import (
	"fmt"

	"github.com/KEINOS/go-wgpu-mat/mat"
)

func main() {
	must := func(err error) {
		if err != nil {
			panic(err)
		}
	}

	ctx, err := mat.NewContext(mat.UseCPU)
	must(err)

	defer ctx.Release()

	matrices := make([]*mat.Matrix, 0, 8)
	newMatrix := func(rows, cols int, data []float32) *mat.Matrix {
		matrix, err := mat.NewMatrix(ctx, rows, cols)
		must(err)

		matrices = append(matrices, matrix)

		if data != nil {
			must(matrix.Write(data))
		}

		return matrix
	}

	defer func() {
		for _, matrix := range matrices {
			matrix.Release()
		}
	}()

	inputs := newMatrix(3, 2, []float32{
		1, 2,
		3, 4,
		5, 6,
	})
	weights := newMatrix(2, 2, []float32{
		0.5, -0.25,
		0.25, 0.75,
	})

	// These sample values stand in for gradients calculated by a loss function.
	outputGradient := newMatrix(3, 2, []float32{
		-0.25, 0.5,
		0.5, -0.5,
		0.75, 0.25,
	})
	inputsTransposed := newMatrix(2, 3, nil)
	weightsTransposed := newMatrix(2, 2, nil)
	weightGradient := newMatrix(2, 2, nil)
	biasGradient := newMatrix(1, 2, nil)
	inputGradient := newMatrix(3, 2, nil)

	// dW = Xᵀ × dY and dX = dY × Wᵀ.
	must(mat.Transp(inputs, inputsTransposed))
	must(mat.MatMul(inputsTransposed, outputGradient, weightGradient))
	// db sums dY over the batch rows, producing one row of bias gradients.
	must(mat.ReduceSumTo(outputGradient, biasGradient))
	must(mat.Transp(weights, weightsTransposed))
	must(mat.MatMul(outputGradient, weightsTransposed, inputGradient))

	weightValues, err := weightGradient.Read()
	must(err)
	biasValues, err := biasGradient.Read()
	must(err)
	inputValues, err := inputGradient.Read()
	must(err)

	fmt.Printf(
		"dW: [%.2f %.2f; %.2f %.2f]\n",
		weightValues[0],
		weightValues[1],
		weightValues[2],
		weightValues[3],
	)
	fmt.Printf("db: [%.2f %.2f]\n", biasValues[0], biasValues[1])
	fmt.Printf(
		"dX: [%.2f %.2f; %.2f %.2f; %.2f %.2f]\n",
		inputValues[0],
		inputValues[1],
		inputValues[2],
		inputValues[3],
		inputValues[4],
		inputValues[5],
	)
}
Output:
dW: [5.00 0.25; 6.00 0.50]
db: [1.00 0.25]
dX: [-0.25 0.31; 0.38 -0.25; 0.31 0.38]

Index

Examples

Constants

This section is empty.

Variables

View Source
var (
	// ErrNilContext indicates a nil or uninitialized *Context was supplied.
	ErrNilContext = errors.New("context is nil")
	// ErrContextReleased indicates the *Context has already been released.
	ErrContextReleased = errors.New("context is released")
	// ErrContextNotInitialized indicates a zero-value or incomplete Context.
	ErrContextNotInitialized = errors.New("context is not initialized")
	// ErrInvalidMode indicates an unknown or conflicting ContextMode.
	ErrInvalidMode = errors.New("invalid context mode")
	// ErrBackendUnavailable indicates no usable WGPU adapter was found.
	ErrBackendUnavailable = errors.New("backend unavailable")

	// ErrNotInitialized indicates a nil or uninitialized *Matrix was supplied.
	ErrNotInitialized = errors.New("not initialized")
	// ErrReleased indicates the *Matrix has already been released.
	ErrReleased = errors.New("released")
	// ErrInvalidState indicates internally inconsistent matrix metadata.
	ErrInvalidState = errors.New("invalid matrix state")

	// ErrInvalidDimension indicates a non-positive matrix dimension.
	ErrInvalidDimension = errors.New("matrix dimensions must be positive")
	// ErrDimensionMismatch indicates operand shapes are incompatible.
	ErrDimensionMismatch = errors.New("dimension mismatch")
	// ErrLengthMismatch indicates host data has the wrong element count.
	ErrLengthMismatch = errors.New("data length mismatch")
	// ErrContextMismatch indicates operands belong to different contexts.
	ErrContextMismatch = errors.New("matrices must use the same context")
	// ErrAliasedOutput indicates the output matrix aliases an input.
	ErrAliasedOutput = errors.New("out must not alias an input")
	// ErrInvalidProbability indicates a probability outside [0, 1).
	ErrInvalidProbability = errors.New("probability must be in [0, 1)")

	// ErrOverflow indicates a size computation overflowed.
	ErrOverflow = errors.New("overflow")
	// ErrDeviceLimit indicates a request exceeds a device/hardware limit.
	ErrDeviceLimit = errors.New("exceeds device limits")
	// ErrKernelLimit indicates a request exceeds a compute-kernel limit.
	ErrKernelLimit = errors.New("exceeds kernel limits")
)

Sentinel errors returned by the package. Callers should compare against these with errors.Is rather than matching on error strings, e.g.:

err := mat.MatMul(a, b, out)
if errors.Is(err, mat.ErrDimensionMismatch) {
	// handle incompatible shapes
}

Validation and lifecycle errors wrap one of these sentinels, so their classification is stable across releases even though the human-readable message may gain extra detail (such as the offending matrix shapes).

Functions

func AdamDelta added in v0.0.4

func AdamDelta(first, second *Matrix, scale, epsilon float32, out *Matrix) error

AdamDelta computes the negative bias-corrected update delta.

func AdamFirstMoment added in v0.0.4

func AdamFirstMoment(moment, gradient *Matrix, beta float32, out *Matrix) error

AdamFirstMoment computes beta*moment + (1-beta)*gradient.

func AdamSecondMoment added in v0.0.4

func AdamSecondMoment(moment, gradient *Matrix, beta float32, out *Matrix) error

AdamSecondMoment computes beta*moment + (1-beta)*gradient squared.

func Add

func Add(left, right, out *Matrix) error

Add computes out = left + right.

Example
package main

import (
	"fmt"

	"github.com/KEINOS/go-wgpu-mat/mat"
)

func main() {
	ctx, err := mat.NewContext(mat.UseCPU)
	if err != nil {
		panic(err)
	}
	defer ctx.Release()

	leftMatrix, err := mat.NewMatrix(ctx, 2, 2)
	if err != nil {
		panic(err)
	}
	defer leftMatrix.Release()

	rightMatrix, err := mat.NewMatrix(ctx, 1, 2)
	if err != nil {
		panic(err)
	}
	defer rightMatrix.Release()

	out, err := mat.NewMatrix(ctx, 2, 2)
	if err != nil {
		panic(err)
	}
	defer out.Release()

	err = leftMatrix.Write([]float32{1, 2, 3, 4})
	if err != nil {
		panic(err)
	}

	err = rightMatrix.Write([]float32{5, 6})
	if err != nil {
		panic(err)
	}

	err = mat.Add(leftMatrix, rightMatrix, out)
	if err != nil {
		panic(err)
	}

	data, err := out.Read()
	if err != nil {
		panic(err)
	}

	fmt.Println(data)
}
Output:
[6 8 8 10]

func AllFiniteAccumulate added in v0.0.4

func AllFiniteAccumulate(input, flag *Matrix) error

AllFiniteAccumulate leaves flag at one only when its previous value and all input elements are finite. Hardware execution does not read back to host.

func BroadcastTo added in v0.0.2

func BroadcastTo(input, out *Matrix) error

BroadcastTo expands singleton input axes to the shape of out.

Example
package main

import (
	"fmt"

	"github.com/KEINOS/go-wgpu-mat/mat"
)

func main() {
	ctx, err := mat.NewContext(mat.UseCPU)
	if err != nil {
		panic(err)
	}
	defer ctx.Release()

	input, err := mat.NewMatrix(ctx, 1, 2)
	if err != nil {
		panic(err)
	}
	defer input.Release()

	out, err := mat.NewMatrix(ctx, 3, 2)
	if err != nil {
		panic(err)
	}
	defer out.Release()

	if err = input.Write([]float32{4, 7}); err != nil {
		panic(err)
	}
	if err = mat.BroadcastTo(input, out); err != nil {
		panic(err)
	}

	data, err := out.Read()
	if err != nil {
		panic(err)
	}

	fmt.Println(data)
}
Output:
[4 7 4 7 4 7]

func Dropout added in v0.0.4

func Dropout(input *Matrix, probability float32, state RandomState, out *Matrix) error

Dropout applies a deterministic counter-based mask without host readback on hardware adapters. RandomState identifies the first word consumed.

func MatMul

func MatMul(left, right, out *Matrix) error

MatMul computes out = left x right with a WGSL compute kernel. All matrices must belong to the same Context, and out must not alias either input. The result remains in its device buffer until Read is called.

Example
package main

import (
	"fmt"

	"github.com/KEINOS/go-wgpu-mat/mat"
)

func main() {
	ctx, err := mat.NewContext(mat.UseCPU)
	if err != nil {
		panic(err)
	}
	defer ctx.Release()

	leftMatrix, err := mat.NewMatrix(ctx, 2, 2)
	if err != nil {
		panic(err)
	}
	defer leftMatrix.Release()

	rightMatrix, err := mat.NewMatrix(ctx, 2, 2)
	if err != nil {
		panic(err)
	}
	defer rightMatrix.Release()

	out, err := mat.NewMatrix(ctx, 2, 2)
	if err != nil {
		panic(err)
	}
	defer out.Release()

	err = leftMatrix.Write([]float32{1, 2, 3, 4})
	if err != nil {
		panic(err)
	}

	err = rightMatrix.Write([]float32{5, 6, 7, 8})
	if err != nil {
		panic(err)
	}

	err = mat.MatMul(leftMatrix, rightMatrix, out)
	if err != nil {
		panic(err)
	}

	data, err := out.Read()
	if err != nil {
		panic(err)
	}

	fmt.Println(data)
}
Output:
[19 22 43 50]

func Mul added in v0.0.2

func Mul(left, right, out *Matrix) error

Mul computes an elementwise product with 2D broadcasting.

Example
package main

import (
	"fmt"

	"github.com/KEINOS/go-wgpu-mat/mat"
)

func main() {
	ctx, err := mat.NewContext(mat.UseCPU)
	if err != nil {
		panic(err)
	}
	defer ctx.Release()

	left, err := mat.NewMatrix(ctx, 2, 2)
	if err != nil {
		panic(err)
	}
	defer left.Release()

	right, err := mat.NewMatrix(ctx, 1, 2)
	if err != nil {
		panic(err)
	}
	defer right.Release()

	out, err := mat.NewMatrix(ctx, 2, 2)
	if err != nil {
		panic(err)
	}
	defer out.Release()

	if err = left.Write([]float32{1, 2, 3, 4}); err != nil {
		panic(err)
	}
	if err = right.Write([]float32{10, 100}); err != nil {
		panic(err)
	}
	if err = mat.Mul(left, right, out); err != nil {
		panic(err)
	}

	data, err := out.Read()
	if err != nil {
		panic(err)
	}

	fmt.Println(data)
}
Output:
[10 200 30 400]

func RMSNorm

func RMSNorm(input, out *Matrix) error

RMSNorm computes row-wise root-mean-square normalization.

Example
package main

import (
	"fmt"

	"github.com/KEINOS/go-wgpu-mat/mat"
)

func main() {
	ctx, err := mat.NewContext(mat.UseCPU)
	if err != nil {
		panic(err)
	}

	defer ctx.Release()

	inputMatrix, err := mat.NewMatrix(ctx, 1, 2)
	if err != nil {
		panic(err)
	}

	defer inputMatrix.Release()

	out, err := mat.NewMatrix(ctx, 1, 2)
	if err != nil {
		panic(err)
	}

	defer out.Release()

	err = inputMatrix.Write([]float32{3, 4})
	if err != nil {
		panic(err)
	}

	err = mat.RMSNorm(inputMatrix, out)
	if err != nil {
		panic(err)
	}

	data, err := out.Read()
	if err != nil {
		panic(err)
	}

	fmt.Printf("%.4f %.4f\n", data[0], data[1])
}
Output:
0.8485 1.1314

func ReduceMax

func ReduceMax(input, out *Matrix) error

ReduceMax computes row-wise max and stores the result in out.

Example
package main

import (
	"fmt"

	"github.com/KEINOS/go-wgpu-mat/mat"
)

func main() {
	ctx, err := mat.NewContext(mat.UseCPU)
	if err != nil {
		panic(err)
	}

	defer ctx.Release()

	inputMatrix, err := mat.NewMatrix(ctx, 2, 3)
	if err != nil {
		panic(err)
	}

	defer inputMatrix.Release()

	out, err := mat.NewMatrix(ctx, 2, 1)
	if err != nil {
		panic(err)
	}

	defer out.Release()

	err = inputMatrix.Write([]float32{-1, -3, -2, 4, 0, 1})
	if err != nil {
		panic(err)
	}

	err = mat.ReduceMax(inputMatrix, out)
	if err != nil {
		panic(err)
	}

	data, err := out.Read()
	if err != nil {
		panic(err)
	}

	fmt.Println(data)
}
Output:
[-1 4]

func ReduceSum

func ReduceSum(input, out *Matrix) error

ReduceSum computes row-wise sum and stores the result in out.

Example
package main

import (
	"fmt"

	"github.com/KEINOS/go-wgpu-mat/mat"
)

func main() {
	ctx, err := mat.NewContext(mat.UseCPU)
	if err != nil {
		panic(err)
	}

	defer ctx.Release()

	inputMatrix, err := mat.NewMatrix(ctx, 2, 3)
	if err != nil {
		panic(err)
	}

	defer inputMatrix.Release()

	out, err := mat.NewMatrix(ctx, 2, 1)
	if err != nil {
		panic(err)
	}

	defer out.Release()

	err = inputMatrix.Write([]float32{1, 2, 3, 4, 5, 6})
	if err != nil {
		panic(err)
	}

	err = mat.ReduceSum(inputMatrix, out)
	if err != nil {
		panic(err)
	}

	data, err := out.Read()
	if err != nil {
		panic(err)
	}

	fmt.Println(data)
}
Output:
[6 15]

func ReduceSumTo added in v0.0.2

func ReduceSumTo(input, out *Matrix) error

ReduceSumTo sums input axes whose corresponding out dimension is 1.

Example
package main

import (
	"fmt"

	"github.com/KEINOS/go-wgpu-mat/mat"
)

func main() {
	ctx, err := mat.NewContext(mat.UseCPU)
	if err != nil {
		panic(err)
	}
	defer ctx.Release()

	input, err := mat.NewMatrix(ctx, 2, 3)
	if err != nil {
		panic(err)
	}
	defer input.Release()

	out, err := mat.NewMatrix(ctx, 1, 3)
	if err != nil {
		panic(err)
	}
	defer out.Release()

	if err = input.Write([]float32{1, 2, 3, 4, 5, 6}); err != nil {
		panic(err)
	}
	if err = mat.ReduceSumTo(input, out); err != nil {
		panic(err)
	}

	data, err := out.Read()
	if err != nil {
		panic(err)
	}

	fmt.Println(data)
}
Output:
[5 7 9]

func ReshapeTo added in v0.0.2

func ReshapeTo(input, out *Matrix) error

ReshapeTo copies row-major input data to an equal-length output shape.

Example
package main

import (
	"fmt"

	"github.com/KEINOS/go-wgpu-mat/mat"
)

func main() {
	ctx, err := mat.NewContext(mat.UseCPU)
	if err != nil {
		panic(err)
	}
	defer ctx.Release()

	input, err := mat.NewMatrix(ctx, 2, 3)
	if err != nil {
		panic(err)
	}
	defer input.Release()

	out, err := mat.NewMatrix(ctx, 3, 2)
	if err != nil {
		panic(err)
	}
	defer out.Release()

	if err = input.Write([]float32{1, 2, 3, 4, 5, 6}); err != nil {
		panic(err)
	}
	if err = mat.ReshapeTo(input, out); err != nil {
		panic(err)
	}

	data, err := out.Read()
	if err != nil {
		panic(err)
	}

	fmt.Println(data)
}
Output:
[1 2 3 4 5 6]

func Scale

func Scale(input *Matrix, scalar float32, out *Matrix) error

Scale computes out = input * scalar.

Example
package main

import (
	"fmt"

	"github.com/KEINOS/go-wgpu-mat/mat"
)

func main() {
	ctx, err := mat.NewContext(mat.UseCPU)
	if err != nil {
		panic(err)
	}

	defer ctx.Release()

	sourceMatrix, err := mat.NewMatrix(ctx, 2, 2)
	if err != nil {
		panic(err)
	}

	defer sourceMatrix.Release()

	out, err := mat.NewMatrix(ctx, 2, 2)
	if err != nil {
		panic(err)
	}

	defer out.Release()

	err = sourceMatrix.Write([]float32{1, -2, 3, -4})
	if err != nil {
		panic(err)
	}

	err = mat.Scale(sourceMatrix, 0.5, out)
	if err != nil {
		panic(err)
	}

	data, err := out.Read()
	if err != nil {
		panic(err)
	}

	fmt.Println(data)
}
Output:
[0.5 -1 1.5 -2]

func SelectFinite added in v0.0.4

func SelectFinite(candidate, original, flag, out *Matrix) error

SelectFinite copies candidate when flag is one, otherwise original.

func Softmax

func Softmax(input, out *Matrix) error

Softmax computes row-wise softmax for input and stores it in out.

Example
package main

import (
	"fmt"

	"github.com/KEINOS/go-wgpu-mat/mat"
)

func main() {
	ctx, err := mat.NewContext(mat.UseCPU)
	if err != nil {
		panic(err)
	}

	defer ctx.Release()

	inputMatrix, err := mat.NewMatrix(ctx, 1, 3)
	if err != nil {
		panic(err)
	}

	defer inputMatrix.Release()

	out, err := mat.NewMatrix(ctx, 1, 3)
	if err != nil {
		panic(err)
	}

	defer out.Release()

	err = inputMatrix.Write([]float32{1, 2, 3})
	if err != nil {
		panic(err)
	}

	err = mat.Softmax(inputMatrix, out)
	if err != nil {
		panic(err)
	}

	data, err := out.Read()
	if err != nil {
		panic(err)
	}

	fmt.Printf("%.4f %.4f %.4f\n", data[0], data[1], data[2])
}
Output:
0.0900 0.2447 0.6652

func Transp

func Transp(input, out *Matrix) error

Transp computes out = input^T.

Example
package main

import (
	"fmt"

	"github.com/KEINOS/go-wgpu-mat/mat"
)

func main() {
	ctx, err := mat.NewContext(mat.UseCPU)
	if err != nil {
		panic(err)
	}

	defer ctx.Release()

	inputMatrix, err := mat.NewMatrix(ctx, 2, 3)
	if err != nil {
		panic(err)
	}

	defer inputMatrix.Release()

	out, err := mat.NewMatrix(ctx, 3, 2)
	if err != nil {
		panic(err)
	}

	defer out.Release()

	err = inputMatrix.Write([]float32{1, 2, 3, 4, 5, 6})
	if err != nil {
		panic(err)
	}

	err = mat.Transp(inputMatrix, out)
	if err != nil {
		panic(err)
	}

	data, err := out.Read()
	if err != nil {
		panic(err)
	}

	fmt.Println(data)
}
Output:
[1 4 2 5 3 6]

Types

type Context

type Context struct {
	// contains filtered or unexported fields
}

Context holds a live WGPU Instance, Adapter, and Device. Create one via NewContext; release it with Release when done.

func NewContext

func NewContext(modes ...ContextMode) (*Context, error)

NewContext creates a compute context.

The package registers required backends internally, so callers do not need blank-import backend packages.

When no mode is provided, UseAuto is selected by default.

ctx, err := NewContext()       // same as NewContext(UseAuto)
ctx, err := NewContext(UseCPU) // force software/fallback adapter
ctx, err := NewContext(UseGPU) // high-performance GPU adapter

func (*Context) Close

func (c *Context) Close() error

Close releases the context and always returns nil. It allows Context to be used as an io.Closer while preserving the idempotent Release API.

func (*Context) Mode

func (c *Context) Mode() ContextMode

Mode reports the mode requested when this Context was created. For UseAuto, the actual adapter may be either hardware or software.

func (*Context) Release

func (c *Context) Release()

Release frees the Device, Adapter, and Instance in reverse order. It is a no-op when called on a nil receiver or more than once. Release must not run concurrently with matrix operations using this Context.

func (*Context) Released

func (c *Context) Released() bool

Released reports whether Release has been called.

func (*Context) Stats added in v0.0.2

func (c *Context) Stats() Stats

Stats returns a concurrency-safe snapshot of cumulative context activity. It can be called before or after Release.

Example
package main

import (
	"fmt"

	"github.com/KEINOS/go-wgpu-mat/mat"
)

func main() {
	ctx, err := mat.NewContext(mat.UseCPU)
	if err != nil {
		panic(err)
	}
	defer ctx.Release()

	before := ctx.Stats()

	input, err := mat.NewMatrix(ctx, 1, 1)
	if err != nil {
		panic(err)
	}
	defer input.Release()

	if err = input.Write([]float32{42}); err != nil {
		panic(err)
	}
	if _, err = input.Read(); err != nil {
		panic(err)
	}

	after := ctx.Stats()

	fmt.Println(after.HostReadCount - before.HostReadCount)
	fmt.Println(after.HostReadBytes - before.HostReadBytes)
	fmt.Println(after.HostWriteCount - before.HostWriteCount)
	fmt.Println(after.HostWriteBytes - before.HostWriteBytes)
}
Output:
1
4
1
4

type ContextMode

type ContextMode uint8

ContextMode specifies which adapter type NewContext should prefer.

const (
	// UseGPU requires a non-CPU, high-performance adapter.
	UseGPU ContextMode = iota
	// UseCPU forces a fallback adapter (software backend).
	UseCPU
	// UseAuto tries a high-performance GPU adapter first, then retries with a
	// software/fallback adapter if no GPU adapter is available.
	UseAuto
)

func (ContextMode) String

func (m ContextMode) String() string

String returns the stable name of the context mode.

type Matrix

type Matrix struct {
	// contains filtered or unexported fields
}

Matrix represents a 2D float32 array stored in a WGPU storage buffer.

Data is stored in row-major order: element (r, c) is at index r*Cols() + c within the underlying GPU buffer.

Kernelized GPU operations submit commands to the device queue. CPU fallback and host compatibility operations complete synchronously. Read waits for pending device work before returning host data.

func NewMatrix

func NewMatrix(ctx *Context, rows, cols int) (*Matrix, error)

NewMatrix allocates a WGPU buffer for a rows x cols float32 matrix. The initial buffer contents are undefined; call Write to upload data before performing calculations.

Example

Example of creating a new matrix for a compute context.

package main

import (
	"fmt"

	"github.com/KEINOS/go-wgpu-mat/mat"
)

func main() {
	ctx, err := mat.NewContext(mat.UseCPU)
	if err != nil {
		panic(err)
	}
	defer ctx.Release()

	mtx, err := mat.NewMatrix(ctx, 2, 3)
	if err != nil {
		panic(err)
	}
	defer mtx.Release()

	fmt.Printf("Type: %T\n", mtx)
	fmt.Printf("Matrix: %dx%d\n", mtx.Rows(), mtx.Cols())
}
Output:
Type: *mat.Matrix
Matrix: 2x3

func (*Matrix) Close

func (m *Matrix) Close() error

Close releases the matrix and always returns nil. It allows Matrix to be used as an io.Closer while preserving the idempotent Release API.

func (*Matrix) Cols

func (m *Matrix) Cols() int

Cols returns the number of columns.

func (*Matrix) Len

func (m *Matrix) Len() int

Len returns the number of matrix elements.

func (*Matrix) Read

func (m *Matrix) Read() ([]float32, error)

Read downloads the matrix data from the GPU and returns it as a flat float32 slice in row-major order (length = m.Len()).

func (*Matrix) Release

func (m *Matrix) Release()

Release frees the GPU buffer held by this matrix. Calling Release more than once is safe (subsequent calls are no-ops). Release must not run concurrently with operations using the matrix.

func (*Matrix) Released

func (m *Matrix) Released() bool

Released reports whether Release has been called.

func (*Matrix) Rows

func (m *Matrix) Rows() int

Rows returns the number of rows.

func (*Matrix) Shape

func (m *Matrix) Shape() Shape

Shape returns the matrix shape as an immutable-by-copy value.

func (*Matrix) String

func (m *Matrix) String() string

String returns a compact diagnostic representation of the matrix.

func (*Matrix) Write

func (m *Matrix) Write(data []float32) error

Write uploads data to the GPU buffer. data must have exactly m.Len() elements.

type RandomState added in v0.0.4

type RandomState struct {
	Seed     uint64
	StreamID uint64
	Counter  uint64
}

RandomState identifies the first counter-based random word for a device operation.

type Shape

type Shape struct {
	// contains filtered or unexported fields
}

Shape is the immutable-by-copy shape of a Matrix.

func (Shape) Cols

func (s Shape) Cols() int

Cols returns the number of columns.

func (Shape) Len

func (s Shape) Len() int

Len returns the number of elements in the shape. Shapes returned by Matrix are always valid and cannot overflow int.

func (Shape) Rows

func (s Shape) Rows() int

Rows returns the number of rows.

func (Shape) String

func (s Shape) String() string

String formats a shape as "rowsxcols".

type Stats added in v0.0.2

type Stats struct {
	HostReadCount           uint64
	HostReadBytes           uint64
	HostWriteCount          uint64
	HostWriteBytes          uint64
	ComputeSubmissionCount  uint64
	ReadbackSubmissionCount uint64
	MatrixAllocationCount   uint64
	MatrixReleaseCount      uint64
	LiveMatrixBytes         uint64
	PeakLiveMatrixBytes     uint64
}

Stats is an immutable-by-copy snapshot of Context activity.

Host transfer fields include only completed public Matrix.Read and Matrix.Write payload transfers. Submission fields distinguish compute work from readback copies. Matrix lifetime fields exclude internal staging and uniform buffers.

Directories

Path Synopsis
internal
backends
Package backends registers WGPU backends for mat context creation.
Package backends registers WGPU backends for mat context creation.
pipelinecache
Package pipelinecache provides an internal cache for compute pipelines.
Package pipelinecache provides an internal cache for compute pipelines.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL