vkML 0.1.0

Creation

11 functions — 11 documented.

tensor

tensor(data, dtype=None, device=None, requires_grad=False) → 'Tensor'
CPUVulkan

Create a tensor from a NumPy array.

The data is copied, never aliased, so mutating the source array afterwards cannot change the tensor. Dtype follows the array unless one is given; a float64 array is narrowed to float32, because no backend implements float64.

Parameters

data (numpy.ndarray)
Values to copy. Any shape, including 0-d.
device (device = cpu) optional
Where the tensor lives. Vulkan devices must be initialised with init_vulkan first.
requires_grad (bool = False) optional
Whether autograd should track operations on it.

Returns

A new tensor holding a copy of data.

Example

>>> import numpy as np, vkml
>>> x = vkml.tensor(np.array([[1.0, 2.0], [3.0, 4.0]], dtype=np.float32))
>>> x.shape
(2, 2)
>>> vkml.init_vulkan(0)
'vulkan:0'
>>> g = vkml.tensor(np.zeros((4, 4), dtype=np.float32), device=vkml.device("vulkan:0"))
>>> g.device
device('vulkan:0')

Implementation

CPU kernelcomposed from other operators
Vulkan shadercomposed, or dispatched through a shared kernel
Gradient rulenone — backward through it raises
Tests (≥261)test_attribution.py test_autograd_vs_torch.py test_backend_parity.py test_data_and_serialize.py test_decision_facts.py test_device_limits.py test_device_report.py test_extreme_values.py test_f16.py test_invariants.py test_layout_and_scale.py test_nan_semantics.py test_nn_vs_torch.py test_operand_packing.py test_ops_vs_torch.py test_vulkan_kernels.py

See also zeros, ones, from_numpy, arange

zeros

zeros(shape: Sequence[int], dtype: dtype = dtype.float32, device: device = device('cpu')) → Tensor
CPUVulkan

Create a tensor of the given shape filled with zeros.

Parameters

shape (Sequence[int])
Extent of each axis.
dtype (dtype = float32) optional
Element type.
device (device = cpu) optional
Where to allocate.

Returns

A new tensor of shape, every element zero.

Example

>>> vkml.zeros([2, 3]).numpy()
array([[0., 0., 0.],
       [0., 0., 0.]], dtype=float32)

Implementation

Declared ininclude/vkml/api/tensor.h:53
CPU kernelcomposed from other operators
Vulkan shadercomposed, or dispatched through a shared kernel
Gradient rulenone — backward through it raises
Tests (≥2)test_invariants.py test_ops_vs_torch.py

See also ones, full, tensor

ones

ones(shape: Sequence[int], dtype: dtype = dtype.float32, device: device = device('cpu')) → Tensor
CPUVulkan

Create a tensor of the given shape filled with ones.

Parameters

shape (Sequence[int])
Extent of each axis.
dtype (dtype = float32) optional
Element type.
device (device = cpu) optional
Where to allocate.

Returns

A new tensor of shape, every element one.

Example

>>> vkml.ones([2, 2]).numpy()
array([[1., 1.],
       [1., 1.]], dtype=float32)

Implementation

Declared ininclude/vkml/api/tensor.h:56
CPU kernelcomposed from other operators
Vulkan shadercomposed, or dispatched through a shared kernel
Gradient rulenone — backward through it raises
Tests (≥1)test_invariants.py

See also zeros, full, tensor

full

full(shape: Sequence[int], value: float, dtype: dtype = dtype.float32, device: device = device('cpu')) → Tensor
CPUVulkan

Create a tensor of the given shape filled with one value.

The fill value travels as a push constant rather than as a staged buffer, so no host-to-device copy is involved on the GPU path.

Parameters

shape (Sequence[int])
Extent of each axis.
value (float)
The value every element takes.
dtype (dtype = float32) optional
Element type.
device (device = cpu) optional
Where to allocate.

Returns

A new tensor of shape.

Example

>>> vkml.full([2, 2], 2.5).numpy()
array([[2.5, 2.5],
       [2.5, 2.5]], dtype=float32)

Implementation

Declared ininclude/vkml/api/tensor.h:50
Graph nodeOpKind::Full
CPU kernelsrc/backend/cpu/kernels_movement.cpp:125
Vulkan shadercomposed, or dispatched through a shared kernel
Gradient rulenone — backward through it raises
DecisionsADR 0013
Historycommits touching the CPU kernel
Tests (≥8)test_invariants.py test_nn_vs_torch.py test_ops_vs_torch.py test_vulkan_kernels.py

See also zeros, ones

arange

arange(start: float, stop: float, step: float = 1.0, dtype: dtype = dtype.float32, device: device = device('cpu')) → Tensor
CPUVulkan

Create a 1-D tensor of evenly spaced values over a half-open interval.

The interval is [start, stop)stop is excluded, matching numpy.arange and torch.arange.

Parameters

start (float)
First value.
stop (float)
Exclusive upper bound.
step (float = 1) optional
Spacing between values.
device (device = cpu) optional
Where to allocate.

Returns

A 1-D tensor with ceil((stop - start) / step) elements.

Example

>>> vkml.arange(0, 5, 1).numpy()
array([0., 1., 2., 3., 4.], dtype=float32)

Implementation

Declared ininclude/vkml/api/tensor.h:59
Graph nodeOpKind::Arange
CPU kernelsrc/backend/cpu/kernels_movement.cpp:175
Vulkan shadercomposed, or dispatched through a shared kernel
Gradient rulenone — backward through it raises
Historycommits touching the CPU kernel
Tests (≥1)test_vulkan_kernels.py

rand

rand(shape: Sequence[int], seed: int, offset: int = 0, device: device = device('cpu')) → Tensor
CPUVulkan

Uniform random values in [0, 1), from a counter-based generator.

Uses Philox4x32-10 (src/backend/cpu/philox.h), a counter-based generator rather than a stateful one. The value at each index is a pure function of (seed, offset, index), so it does not matter which invocation computes which element or in what order — the GPU produces the same draw as the CPU without any sequencing between threads.

That is why the signature takes a seed and an offset rather than carrying hidden state: the offset is how you advance the stream between calls.

Each value takes the top 24 bits of a 32-bit output, which is the float significand's width, so every result is exactly representable.

Parameters

shape (Sequence[int])
Extent of each axis.
seed (int)
Identifies the stream.
offset (int = 0) optional
Position within the stream. Advance it between draws.
device (device = cpu) optional
Where to allocate.

Returns

A new tensor of shape with values in [0, 1).

ⓘ Note

Same (seed, offset, shape) gives the same values on every device and every run — this is part of the determinism contract, not a convenience.

Example

>>> a = vkml.rand([4], 42, 0).numpy()
>>> b = vkml.rand([4], 42, 0).numpy()
>>> bool((a == b).all())
True

From the header

[[nodiscard]] Tensor rand(std::span<const int64_t> dims, uint64_t seed, uint64_t offset = 0, Device device = Device::cpu());include/vkml/api/ops.h:227

Uniform values in [0, 1), from a counter-based generator.

A PURE FUNCTION of (seed, offset, element index): the same arguments always give the same tensor, on either backend, however the work is divided. There is no hidden global stream to advance, so two calls sharing a seed and an offset produce identical values -- which is what makes a dropout mask reproducible, and a bug if a training loop forgets to advance the offset.

Deliberately not bit-compatible with PyTorch's generator, and it does not try to be (docs/ARCHITECTURE.md §7.2). Matching another framework's stream would validate nothing about this library; parity is tested distributionally instead.

In the CPU kernel

Uniform values in [0, 1), one per element, from a counter-based generator.

The value depends only on (seed, offset, linear index), so it is identical on both backends and independent of how the work is divided -- see philox.h.

src/backend/cpu/kernels_movement.cpp:203

Implementation

Declared ininclude/vkml/api/ops.h:227
Graph nodeOpKind::Rand
CPU kernelsrc/backend/cpu/kernels_movement.cpp:203
Vulkan shadershaders/rand.comp (70 lines)
Gradient rulenone — backward through it raises
Historycommits touching the CPU kernel
Tests (≥6)test_ops_vs_torch.py test_vulkan_kernels.py

See also zeros, dropout

from_numpy

from_numpy(arr, dtype=None, device=None) → 'Tensor'
CPUVulkan

Create a CPU tensor from a NumPy array.

The data is copied. Use tensor when a device or requires_grad is wanted.

Parameters

array (numpy.ndarray)
Values to copy.

Returns

A new CPU tensor.

Example

>>> vkml.from_numpy(np.array([1.0, 2.0], dtype=np.float32)).numpy()
array([1., 2.], dtype=float32)

Implementation

CPU kernelcomposed from other operators
Vulkan shadercomposed, or dispatched through a shared kernel
Gradient rulenone — backward through it raises
Testsnone found by name

See also tensor, asarray

asarray

asarray(t: 'Tensor') → '_np.ndarray'
CPUVulkan

Copy a tensor's contents out into a NumPy array.

The inverse direction to from_numpy. Forces realization: a lazily built graph has to run before there are values to copy.

Parameters

tensor (Tensor)
The tensor to read.

Returns

A new NumPy array holding a copy.

Example

>>> vkml.asarray(vkml.ones([3]))
array([1., 1., 1.], dtype=float32)

Implementation

CPU kernelcomposed from other operators
Vulkan shadercomposed, or dispatched through a shared kernel
Gradient rulenone — backward through it raises
Testsnone found by name

See also from_numpy, tensor

zeros_like

zeros_like(input: Tensor) → Tensor
CPUVulkan

Create a tensor of zeros with the same shape, dtype and device as the input.

Shorthand for zeros(x.shape, dtype=x.dtype, device=x.device). Every property is taken from the input, so an f16 input gives an f16 result — nothing falls back to the float32 default that the explicit form would apply if you forgot to pass dtype.

The shape is the logical one, so a transposed view gives the transposed shape.

Parameters

input (Tensor)
Tensor whose shape, dtype and device to copy.

Returns

A new tensor shaped like input, every element zero.

ⓘ Note

The input's values are not read and its graph is not realized — only its shape, dtype and device are used.

Example

>>> x = vkml.tensor([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]])
>>> vkml.zeros_like(x).numpy()
array([[0., 0., 0.],
       [0., 0., 0.]], dtype=float32)
>>> vkml.zeros_like(x.astype(vkml.dtype.float16)).dtype
dtype.float16

Implementation

Declared ininclude/vkml/api/ops.h:82
CPU kernelcomposed from other operators
Vulkan shadercomposed, or dispatched through a shared kernel
Gradient rulenone — backward through it raises
Tests (≥1)test_invariants.py

See also zeros, ones_like, full_like

ones_like

ones_like(input: Tensor) → Tensor
CPUVulkan

Create a tensor of ones with the same shape, dtype and device as the input.

Shorthand for ones(x.shape, dtype=x.dtype, device=x.device). See zeros_like for how the input's properties are inherited.

Parameters

input (Tensor)
Tensor whose shape, dtype and device to copy.

Returns

A new tensor shaped like input, every element one.

Example

>>> x = vkml.tensor([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]])
>>> vkml.ones_like(x).numpy()
array([[1., 1., 1.],
       [1., 1., 1.]], dtype=float32)

Implementation

Declared ininclude/vkml/api/ops.h:83
CPU kernelcomposed from other operators
Vulkan shadercomposed, or dispatched through a shared kernel
Gradient rulenone — backward through it raises
Testsnone found by name

See also ones, zeros_like, full_like

full_like

full_like(input: Tensor, value: float) → Tensor
CPUVulkan

Create a tensor filled with a value, shaped like the input.

Shorthand for full(x.shape, value, dtype=x.dtype, device=x.device). The value is given as a float and converted to the input's dtype, so a value outside that type's range will not survive the conversion.

Parameters

input (Tensor)
Tensor whose shape, dtype and device to copy.
value (float)
The fill value, converted to input's dtype.

Returns

A new tensor shaped like input, every element value.

Example

>>> x = vkml.tensor([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]])
>>> vkml.full_like(x, 7.0).numpy()
array([[7., 7., 7.],
       [7., 7., 7.]], dtype=float32)

Implementation

Declared ininclude/vkml/api/ops.h:84
CPU kernelcomposed from other operators
Vulkan shadercomposed, or dispatched through a shared kernel
Gradient rulenone — backward through it raises
Testsnone found by name

See also full, zeros_like, ones_like

vkML — Vulkan-first machine learning in C++20. Apache-2.0. Signatures on this page are generated from the installed module.