vkML 0.1.0

Devices & introspection

22 functions — 22 documented.

init_vulkan

init_vulkan(index: int = 0) → str
CPUVulkan

Initialise a Vulkan device and make it available for allocation.

Must be called before any tensor is placed on vulkan:N. Creates the device, the allocator and a staging buffer, so it is a once-per-process cost rather than a per-tensor one.

Parameters

index (int = 0) optional
Which physical device, in enumeration order.

Returns

The device string that was initialised.

⚠ Warning

Enumeration order is not stable across environments. The same machine can report its discrete GPU at index 0 natively and at index 1 inside a container, with a software rasteriser appearing as a third device. Use best_device when the intent is "the fastest one", and select on device_type from vulkan_device_reports when the intent is a specific class of device.

Example

>>> vkml.init_vulkan(0)
'vulkan:0'

Implementation

CPU kernelcomposed from other operators
Vulkan shadercomposed, or dispatched through a shared kernel
Gradient rulenone — backward through it raises
DecisionsADR 0008
Tests (≥14)test_device_limits.py test_device_report.py test_invariants.py test_vulkan_kernels.py

See also best_device, vulkan_device_reports, available_devices

available_devices

available_devices() → list[device]
CPUVulkan

Every device that can currently hold a tensor.

Returns

A list of device objects, always including cpu.

From the header

[[nodiscard]] std::vector<Device> available_devices();include/vkml/backend/api/backend.h:140

Devices with a registered backend.

Implementation

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

See also best_device, init_vulkan

best_device

best_device() → 'tuple[device, str]'
CPUVulkan

Pick the most capable available device, preferring discrete Vulkan hardware.

Returns

A (device, reason) pair. The reason names the device and why it was chosen, so it can be logged rather than guessed at.

Example

>>> dev, why = vkml.best_device()
>>> print(why)                          # doctest: +SKIP
using Vulkan device 0: AMD Radeon RX 5600M (RADV NAVI10) (discrete, Vulkan 1.4.354, driver radv)

Implementation

CPU kernelcomposed from other operators
Vulkan shadercomposed, or dispatched through a shared kernel
Gradient rulenone — backward through it raises
Tests (≥1)test_device_report.py

See also init_vulkan, available_devices, vulkan_device_reports

vulkan_available

vulkan_available() → bool
CPUVulkan

Whether a usable Vulkan device was found.

Returns

True if at least one device passed the required-feature check.

From the header

[[nodiscard]] bool vulkan_available();include/vkml/backend/vulkan/vulkan_backend.h:224

True when at least one Vulkan device is present.

Implementation

Declared ininclude/vkml/backend/vulkan/vulkan_backend.h:224
CPU kernelcomposed from other operators
Vulkan shadercomposed, or dispatched through a shared kernel
Gradient rulenone — backward through it raises
Tests (≥2)test_data_and_serialize.py test_device_report.py

See also vulkan_unavailable_reason, vulkan_capabilities

vulkan_device_count

vulkan_device_count() → int
CPUVulkan

How many Vulkan devices were enumerated.

Returns

An integer, including devices that failed the feature check.

Implementation

Declared ininclude/vkml/backend/vulkan/vulkan_backend.h:226
CPU kernelcomposed from other operators
Vulkan shadercomposed, or dispatched through a shared kernel
Gradient rulenone — backward through it raises
Tests (≥4)test_device_report.py

See also vulkan_device_names, vulkan_device_reports

vulkan_device_names

vulkan_device_names() → list[str]
CPUVulkan

The name of each enumerated Vulkan device.

Returns

A list of strings, in enumeration order.

Implementation

Declared ininclude/vkml/backend/vulkan/vulkan_backend.h:228
CPU kernelcomposed from other operators
Vulkan shadercomposed, or dispatched through a shared kernel
Gradient rulenone — backward through it raises
Tests (≥1)test_device_report.py

See also vulkan_device_reports, init_vulkan

vulkan_device_reports

vulkan_device_reports() → list
CPUVulkan

A full capability report per device.

Each entry carries the device name, device_type (discrete, integrated or cpu), driver_name, the required and optional features, and the limits that decide which kernels can run — subgroup size and its controllable range, workgroup invocations, shared memory, push-constant bytes, memory heaps.

Select on device_type rather than on index when a specific class of device is wanted; the index is not stable across environments.

Returns

A list of dicts, one per device.

From the header

[[nodiscard]] std::vector<DeviceReport> vulkan_device_reports();include/vkml/backend/vulkan/vulkan_backend.h:234

Describes every visible device WITHOUT creating a logical device.

Empty when no Vulkan loader or no device is present, rather than throwing: "this machine has no Vulkan" is an answer a report needs to be able to give.

Implementation

Declared ininclude/vkml/backend/vulkan/vulkan_backend.h:234
CPU kernelcomposed from other operators
Vulkan shadercomposed, or dispatched through a shared kernel
Gradient rulenone — backward through it raises
Tests (≥8)test_device_report.py

See also vulkan_capabilities, best_device, init_vulkan

vulkan_capabilities

vulkan_capabilities(index: int = 0) → dict
CPUVulkan

The capability report for one initialised device.

Parameters

index (int = 0) optional
Which device.

Returns

A dict of features and limits.

Implementation

CPU kernelcomposed from other operators
Vulkan shadercomposed, or dispatched through a shared kernel
Gradient rulenone — backward through it raises
Tests (≥4)test_device_limits.py test_invariants.py test_vulkan_kernels.py

See also vulkan_device_reports

vulkan_stats

vulkan_stats(index: int = 0) → dict
CPUVulkan

Allocation and dispatch counters for one device.

Parameters

index (int = 0) optional
Which device.

Returns

A dict of counters.

Implementation

CPU kernelcomposed from other operators
Vulkan shadercomposed, or dispatched through a shared kernel
Gradient rulenone — backward through it raises
Tests (≥8)test_invariants.py test_vulkan_kernels.py

See also vulkan_pipeline_stats, vulkan_last_profile

vulkan_pipeline_stats

vulkan_pipeline_stats(index: int = 0) → list
CPUVulkan

Compiler statistics for every pipeline created so far.

Reports what the shader compiler produced per pipeline — register counts, spilled scratch, occupancy — which is how the register model in the GEMM work was fitted and tested. Because each geometry compiles to an independent pipeline through specialisation constants, they benchmark and report separately.

Parameters

index (int = 0) optional
Which device.

Returns

A list of dicts, one per pipeline.

ⓘ Note

Only populated when the driver supports pipeline executable properties. VKML_VULKAN_NO_PIPELINE_STATS=1 disables collection.

Implementation

CPU kernelcomposed from other operators
Vulkan shadercomposed, or dispatched through a shared kernel
Gradient rulenone — backward through it raises
DecisionsADR 0011
Tests (≥3)test_device_limits.py test_invariants.py test_vulkan_kernels.py

See also vulkan_stats, vulkan_last_profile

vulkan_timestamps_supported

vulkan_timestamps_supported(index: int = 0) → bool
CPUVulkan

Whether the device can timestamp GPU work.

Parameters

index (int = 0) optional
Which device.

Returns

True if timestamp queries are usable.

ⓘ Note

A device may report valid timestamp bits and then never advance the counter — one virtualised device does exactly that — so a True here is necessary but not sufficient for a meaningful profile.

Implementation

CPU kernelcomposed from other operators
Vulkan shadercomposed, or dispatched through a shared kernel
Gradient rulenone — backward through it raises
Tests (≥2)test_invariants.py

See also vulkan_last_profile, vulkan_set_profiling

vulkan_unavailable_reason

vulkan_unavailable_reason() → str
CPUVulkan

Why Vulkan is unavailable, when it is.

Names the first required feature that was missing, rather than reporting a generic failure — the required set is bufferDeviceAddress, scalarBlockLayout and timelineSemaphore, and a device lacking any of them cannot run vkML's kernels at all.

Returns

A string, empty when Vulkan is available.

From the header

[[nodiscard]] std::string vulkan_unavailable_reason();include/vkml/backend/vulkan/vulkan_backend.h:242

Empty when a device is visible; otherwise why none is, in a form a person reading a bug report can act on.

"No devices" has two quite different causes -- the loader cannot create an instance at all, or it creates one that enumerates nothing -- and telling them apart is most of the diagnosis on hardware nobody here can inspect.

Implementation

Declared ininclude/vkml/backend/vulkan/vulkan_backend.h:242
CPU kernelcomposed from other operators
Vulkan shadercomposed, or dispatched through a shared kernel
Gradient rulenone — backward through it raises
Tests (≥2)test_device_report.py

See also vulkan_available, vulkan_capabilities

vulkan_last_profile

vulkan_last_profile(index: int = 0) → list[tuple[str, float]]
CPUVulkan

Timings from the most recent profiled run.

Parameters

index (int = 0) optional
Which device.

Returns

A list of (label, milliseconds) pairs.

⚠ Warning

Labelled by operator, not by kernel. The entries are real per-operation GPU time, not submission totals — timestamps are written and resolved per node. What they cannot tell you is which KERNEL ran: a matmul entry does not distinguish the naive kernel from the register-blocked one, nor show split-K's partitions. Joining cost to kernel choice needs a shared dispatch identity, which is designed but not yet implemented. Until then, attribution comes from indirect evidence such as batch scaling or device substitution.

Implementation

CPU kernelcomposed from other operators
Vulkan shadercomposed, or dispatched through a shared kernel
Gradient rulenone — backward through it raises
Tests (≥3)test_invariants.py

See also vulkan_submit_ms, vulkan_set_profiling, vulkan_pipeline_stats

vulkan_profile_records

vulkan_profile_records(index: int = 0) → list
CPUVulkan

Measured GPU intervals carrying the identity of what they measured.

The same intervals vulkan_last_profile returns, plus a dispatch field. Join it against decisions() on the same field to answer what did this kernel cost — a question neither side can answer alone.

The profiler deliberately does not know which kernel ran, and the planner deliberately does not know what anything cost. Identity is a third fact, owned by the recorder, describing nothing. That is what stops kernel selection acquiring a second owner.

Parameters

index (int = 0) optional
Which device.

Returns

A list of dicts with label, gpu_ms, start_ms, submission and dispatch.

ⓘ Note

dispatch is 0 when the interval is not a dispatch — the whole-submission entry is the case that exists today. Compare ids for equality only; they are opaque and will widen when multiple queues arrive.

⚠ Warning

An entry is an INTERVAL, not a duration. start_ms places it inside its own submission, and that is the only admissible way to combine several: a dispatch's bracket closes at a global drain point, so concurrent dispatches each report a window reaching the end of the group. Sum their durations and split-K's sixteen partitions total 2.32 ms inside a 0.20 ms submission; take the union of their intervals and they total 0.196 ms.

Implementation

CPU kernelcomposed from other operators
Vulkan shadercomposed, or dispatched through a shared kernel
Gradient rulenone — backward through it raises
Tests (≥1)test_attribution.py

See also vulkan_last_profile, vulkan_profile_history, decisions, record_decisions

vulkan_profile_history

vulkan_profile_history(index: int = 0) → list
CPUVulkan

Every retained submission's intervals, oldest first.

Group by submission before doing anything else. start_ms is measured from that submission's own window, so intervals from two submissions are not on a common line; and whole-submit windows may be summed across submissions — they are serial — where the intervals inside one may not.

vkml.attribution is the worked consumer: it joins these against decisions() and partitions a step's wall time into GPU busy, GPU idle inside submissions, and host and driver.

Parameters

index (int = 0) optional
Which device.

Returns

A list of dicts, the same shape vulkan_profile_records returns.

⚠ Warning

Empty unless vulkan_set_profile_history asked for retention. Costing nothing until it is asked for is the point.

Implementation

CPU kernelcomposed from other operators
Vulkan shadercomposed, or dispatched through a shared kernel
Gradient rulenone — backward through it raises
Tests (≥2)test_attribution.py

See also vulkan_set_profile_history, vulkan_profile_submissions_resolved, vulkan_profile_records

vulkan_set_profile_history

vulkan_set_profile_history(submissions: int, index: int = 0) → None
CPUVulkan

Retain the last N submissions' intervals instead of only the most recent.

vulkan_profile_records covers one submission. A CIFAR training step makes thirty-nine, so anything reasoning about a STEP had nothing to read.

Bounded and opt-in: the window drops its oldest submission rather than growing without limit, and 0 disables it and frees what was held. Retention only — nothing here interprets what it stores.

Parameters

submissions (int)
How many to keep. 0 disables.
index (int = 0) optional
Which device.

Returns

None.

ⓘ Note

Submissions with no dispatch — a download is a copy — have nothing to time and are never retained, so the window holds fewer submissions than the backend made.

Implementation

CPU kernelcomposed from other operators
Vulkan shadercomposed, or dispatched through a shared kernel
Gradient rulenone — backward through it raises
Tests (≥2)test_attribution.py

See also vulkan_profile_history, vulkan_profile_submissions_resolved, vulkan_set_profiling

vulkan_profile_submissions_resolved

vulkan_profile_submissions_resolved(index: int = 0) → int
CPUVulkan

Submissions offered to the retention window, including any it dropped.

The way to tell a truncated report from a short one. Compare against the distinct submission values in vulkan_profile_history(): if this is larger, the window dropped its oldest entries, every per-kernel row understates, and the difference silently lands in whatever bucket absorbs the remainder.

The parallel to decisions_published, and it exists for the same reason.

Parameters

index (int = 0) optional
Which device.

Returns

An integer.

Implementation

CPU kernelcomposed from other operators
Vulkan shadercomposed, or dispatched through a shared kernel
Gradient rulenone — backward through it raises
Tests (≥1)test_attribution.py

See also vulkan_profile_history, vulkan_set_profile_history, decisions_published

vulkan_submit_ms

vulkan_submit_ms(profile) → 'float'
CPUVulkan

Total GPU milliseconds across a profile's submissions.

Parameters

profile (list)
The result of vulkan_last_profile.

Returns

A float.

Implementation

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 vulkan_last_profile

vulkan_set_profiling

vulkan_set_profiling(enabled: bool, index: int = 0) → None
CPUVulkan

Turn GPU timing on or off for a device.

Parameters

enabled (bool)
Whether to record timings.
index (int = 0) optional
Which device.

Implementation

CPU kernelcomposed from other operators
Vulkan shadercomposed, or dispatched through a shared kernel
Gradient rulenone — backward through it raises
Tests (≥6)test_attribution.py test_invariants.py

See also vulkan_last_profile, vulkan_timestamps_supported

vulkan_set_subgroup_override

vulkan_set_subgroup_override(size: int, index: int = 0) → None
CPUVulkan

Force a subgroup width, for testing.

A testing facility rather than a tuning knob. The device reports a controllable range — 32 to 64 on the development GPU — and pinning a width inside it is how a kernel's dependence on subgroup size is tested without different hardware.

Parameters

index (int = 0) optional
Which device.
size (int)
The width to force. 0 restores the driver's choice.

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 vulkan_capabilities

vulkan_synchronize

vulkan_synchronize(index: int = 0) → None
CPUVulkan

Block until every submission has completed.

Anything timing a region with a host clock must call this before stopping it. Work that has been SUBMITTED has not been measured, and a wall clock stopped early reports the submission cost and none of the execution.

Parameters

index (int = 0) optional
Which device.

Returns

None.

ⓘ Note

Reading a result back — .numpy(), .item() — already waits, so this is for the case where nothing did.

Implementation

CPU kernelcomposed from other operators
Vulkan shadercomposed, or dispatched through a shared kernel
Gradient rulenone — backward through it raises
Tests (≥4)test_invariants.py

See also vulkan_set_profiling, vulkan_profile_history

set_log_level

set_log_level(level: LogLevel) → None
CPUVulkan

Set the minimum severity vkML logs.

Parameters

level (LogLevel)
OFF, ERROR, WARN, INFO, DEBUG or TRACE.
ⓘ Note

VKML_VULKAN_DEBUG=1 raises Vulkan-specific tracing separately, and logs every dispatch with its shape and grid.

From the header

void set_log_level(LogLevel level) noexcept;include/vkml/util/log.h:45

Messages below this level are dropped. Default: Info (Release) / Debug (Debug).

Implementation

Declared ininclude/vkml/util/log.h:45
CPU kernelcomposed from other operators
Vulkan shadercomposed, or dispatched through a shared kernel
Gradient rulenone — backward through it raises
Tests (≥15)test_device_limits.py test_device_report.py test_invariants.py test_vulkan_kernels.py

See also vulkan_stats

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