class PackedMatrix Created by dots_pack() or hammings_pack() and used with dots_packed(), hammings_packed(), jaccards_packed(), angulars_packed(), euclideans_packed(), or the @ operator.
Packed matrix kernels are the right tool when the right-hand side is reused across many query batches.
This is the GEMM-like story.
import numpy as np
import numkong as nk
left = np.random.randn(128, 768).astype(np.float32)
right = np.random.randn(10_000, 768).astype(np.float32)
right_packed = nk.dots_pack(right, dtype="float32") # pack once, reuse many times
scores = nk.dots_packed(left, right_packed) # equivalent to left @ right.T
assert scores.shape == (128, 10_000)
assert right_packed.nbytes == nk.PackedMatrix.pack_size(10_000, 768, dtype="float32")Important runtime rules from the current implementation:
a must be rank-2a must have contiguous rowsout, when provided, must be C-contiguous with the expected dtyperows_begin and rows_end split the left operand rowsThe arithmetic advantages are:
Bangulars_packed and euclideans_packedPacking itself does not require aligned caller buffers. The packed object owns its internal payload and handles the layout under the hood.
Tensor @ PackedMatrix is also supported and maps to the same packed dot-product path.
cdist is the NumPy/SciPy-shaped all-pairs entrypoint.
It handles rectangular matrix pairs and symmetric self-distance cases.
import numpy as np
import numkong as nk
queries = np.random.randn(100, 768).astype(np.float32)
database = np.random.randn(10_000, 768).astype(np.float32)
pairwise = nk.angular(queries, database[:100]) # rectangular broadcasted pairwise call
all_pairs = nk.cdist(queries, database, metric="angular") # scipy.spatial.distance.cdist analogue
assert np.asarray(pairwise).shape == (100, 100)
assert np.asarray(all_pairs).shape == (100, 10_000)cdist and the packed and symmetric kernels take a threads= argument, where 0 means every logical processor, and row ranges are still available for partitioning the work yourself. dots_pack and hammings_pack take it too, splitting the packed matrix by columns.
Symmetric kernels solve a different problem from packed cross-matrix kernels.
They compute self-similarity or self-distance matrices.
This is the SYRK-like story.
import numpy as np
import numkong as nk
vectors = np.random.randn(1024, 768).astype(np.float32)
out = nk.zeros((1024, 1024), dtype="float64")
nk.dots_symmetric(vectors, out=out, rows_begin=0, rows_end=256)
nk.dots_symmetric(vectors, out=out, rows_begin=256, rows_end=512)
assert out.shape == (1024, 1024)This family has different economics from packed GEMM-like work.
It avoids duplicate (i, j) and (j, i) evaluations.
It is naturally partitioned by row windows of one square output.
angulars_symmetric and euclideans_symmetric also benefit from reuse of dot-product-derived work inside the symmetric sweep.
That is why these APIs are faster than a nested Python loop over angular(a[i], a[j]).
Ragged scaled-dot-product attention packs the key/value tokens once, then scores many queries against them.
Segments of different lengths share one packed cache, addressed by cumulative key_offsets.
A segment may hold fewer keys than its slot, as a decode cache with spare room does: pass key_lengths too, and the keys past each length are left out of the pack.
import numpy as np
import numkong as nk
lengths = [6, 10] # two ragged segments
offsets = np.array([0, *np.cumsum(lengths)], dtype=np.uint32)
tokens, heads, depth = int(offsets[-1]), 2, 64
k = nk.Tensor(np.random.randn(tokens, heads * depth).astype(np.float32)).astype("bfloat16")
v = nk.Tensor(np.random.randn(tokens, heads * depth).astype(np.float32)).astype("bfloat16")
kv = nk.attention_pack(k, v, key_offsets=offsets, depth=depth)
queries = nk.Tensor(np.random.randn(tokens, heads * depth).astype(np.float32)).astype("bfloat16")
out = nk.attention_packed(queries, kv, query_offsets=offsets)
windowed = nk.attention_packed(queries, kv, query_offsets=offsets, keys_before=3, keys_after=0)
assert kv.shape == (kv.key_value_head_count, kv.depth, kv.segments)Queries align to the end of each segment’s keys: row r of q queries over k keys sits at position r + k - q and sees keys_before keys before it and keys_after after, None being unbounded.
So keys_after=0 is causal for prefill and decode alike, and adding keys_before=w - 1 slides a window of w keys.
Rows that see no key come back as zeros.
For training, the forward also fills a (tokens, heads) log-sum-exp, and attention_packed_gradients turns it, the output and its gradient into BF16 query, key and value gradients under the same band.
CPUs compute them serially, so the cache is packed with nk.Capability.SERIAL:
kv = nk.attention_pack(k, v, key_offsets=offsets, depth=depth, capabilities=nk.Capability.SERIAL)
log_sum_exp = np.empty((tokens, heads), dtype=np.float32)
out = nk.attention_packed(queries, kv, query_offsets=offsets, keys_after=0, log_sum_exp=log_sum_exp)
output_gradient = np.random.randn(tokens, heads * depth).astype(np.float32)
query_gradient, key_gradient, value_gradient = nk.attention_packed_gradients(
queries, kv, query_offsets=offsets, output=out, output_gradient=output_gradient,
log_sum_exp=log_sum_exp, keys_after=0)query_gradient= takes a pre-allocated (tokens, heads * depth) f32 tensor, whose rows may sit in a wider buffer.
With threads=, attention cuts its grid of query tokens × heads into a few windows of equal cost per thread, so a single decode token still spreads over its heads.
PackedMatrixOpaque pre-packed matrix for repeated cross operations.7class PackedMatrix Created by dots_pack() or hammings_pack() and used with dots_packed(), hammings_packed(), jaccards_packed(), angulars_packed(), euclideans_packed(), or the @ operator.
pack_*_size× 2Return packed buffer size in bytes for given dimensions, dtype and capabilities, GPU ones included.@classmethod
def pack__size(
columns: int,
depth: int,
/,
dtype: Literal['uint1', 'int4', 'uint4', 'int64', 'int32', 'int16', 'int8', 'uint64', 'uint32', 'uint16', 'uint8'] | _FloatTypeName | _ComplexTypeName | _MiniFloatType,
capabilities: Capability | int | None = None,
) -> int __repr__*__repr__× 2Return a string representation.def __repr____repr__() -> str columnsNumber of packed vectors, the columns of the result.columns: int depthNumber of columns in the original matrix.depth: int dtypeData type of the packed matrix (like 'bf16' or 'i8').dtype: Literal['uint1', 'int4', 'uint4', 'int64', 'int32', 'int16', 'int8', 'uint64', 'uint32', 'uint16', 'uint8'] | _FloatTypeName | _ComplexTypeName nbytesSize of the packed buffer in bytes.nbytes: int shapeDimensions (columns, depth) read from the packed buffer header.shape: tuple[int, int] AttentionPackedMatrixOpaque pre-packed ragged KV-cache for scaled-dot-product attention.7class AttentionPackedMatrix Created by attention_pack() and used with attention_packed().
segmentsNumber of ragged segments.segments: int key_value_head_countNumber of KV heads.key_value_head_count: int depthChannels per head.depth: int tokensTotal KV tokens across segments.tokens: int shapeDimensions (key_value_head_count, depth, segments) read from the packed buffer header.shape: tuple[int, int, int] dtypeData type of the packed KV-cache.dtype: Literal['uint1', 'int4', 'uint4', 'int64', 'int32', 'int16', 'int8', 'uint64', 'uint32', 'uint16', 'uint8'] | _FloatTypeName | _ComplexTypeName nbytesSize of the packed buffer in bytes.nbytes: int cdistCompute distances between every row of a and every row of b.def cdist(
a: _BufferType,
b: _BufferType,
/,
metric: _MetricName = 'euclidean',
*,
threads: int = 1,
dtype: Literal['uint1', 'int4', 'uint4', 'int64', 'int32', 'int16', 'int8', 'uint64', 'uint32', 'uint16', 'uint8'] | _FloatTypeName | _ComplexTypeName | _MiniFloatType | None = None,
out: _BufferType | None = None,
out_dtype: _FloatTypeName | _ComplexTypeName | _MiniFloatType | None = None,
capabilities: Capability | int | None = ...,
stream: int | None = ...,
) -> float | complex | Tensor | None Similar to scipy.spatial.distance.cdist. Two vectors give a scalar. Matrices give a
[rows,columns] Tensor with a row per row of a and a column per row of b, or fill out and
return None. GPU tensors raise BufferError; pack b with dots_pack() and call the _packed
functions instead.
a_BufferType | First vector or matrix. | |
|---|---|---|
b_BufferType | Second vector or matrix, of the dtype of a. | |
metric_MetricName | Name of the distance, 'euclidean' by default. | |
threadsint | Worker threads. | |
dtypeLiteral['uint1', 'int4', 'uint4', 'int64', 'int32', 'int16', 'int8', 'uint64', 'uint32', 'uint16', 'uint8'] | _FloatTypeName | _ComplexTypeName | _MiniFloatType | None | Input dtype to read both buffers as, overriding the one they report. | |
out_BufferType | None | Output matrix for the distances. | |
out_dtype_FloatTypeName | _ComplexTypeName | _MiniFloatType | None | Result dtype, by default that of out, else float64, complex128 for complex input. | |
capabilitiesCapability | int | None | Capabilities to run within: every CPU one by default, or for packed operands the mask that packed them. | |
streamint | None | A GPU stream pointer, left None on the CPU. |
dots_symmetricCompute the Gram matrix, the symmetric all-pairs dot products, of the rows of vectors.def dots_symmetric(
vectors: _BufferType,
/,
*,
dtype: _FloatTypeName | Literal['uint1', 'int4', 'uint4', 'int64', 'int32', 'int16', 'int8', 'uint64', 'uint32', 'uint16', 'uint8'] | _MiniFloatType | None = None,
out: _BufferType | None = None,
rows_begin: int | None = None,
rows_end: int | None = None,
threads: int = 1,
capabilities: Capability | int | None = ...,
stream: int | None = ...,
) -> Tensor Only the upper triangle of the [count,count] result is guaranteed to be initialized. Returns a
new Tensor, or out when given. On a GPU the call returns before the kernel finishes.
vectors_BufferType | Input matrix of shape [count,depth], or a CUDA or ROCm Tensor from from_dlpack() to run on that GPU. | |
|---|---|---|
dtype_FloatTypeName | Literal['uint1', 'int4', 'uint4', 'int64', 'int32', 'int16', 'int8', 'uint64', 'uint32', 'uint16', 'uint8'] | _MiniFloatType | None | Input dtype to read vectors as, overriding the one it reports. | |
out_BufferType | None | C-contiguous [count,count] output, required on the same GPU for GPU vectors. | |
rows_beginint | None | First row to compute, 0 when None. | |
rows_endint | None | One past the last row to compute, count when None; only the upper triangle
overlapping the rows in range is filled. | |
threadsint | Worker threads, ignored on a GPU. | |
capabilitiesCapability | int | None | Capabilities to run within: every CPU one by default, or for packed operands the mask that packed them. | |
streamint | None | A GPU stream pointer, left None on the CPU. |
hammings_symmetricCompute the symmetric all-pairs Hamming-distance matrix of the rows of vectors.def hammings_symmetric(
vectors: _BufferType,
/,
*,
dtype: Literal['uint1', 'int4', 'uint4', 'int64', 'int32', 'int16', 'int8', 'uint64', 'uint32', 'uint16', 'uint8'] | _MiniFloatType | None = None,
out: _BufferType | None = None,
rows_begin: int | None = None,
rows_end: int | None = None,
threads: int = 1,
capabilities: Capability | int | None = ...,
stream: int | None = ...,
) -> Tensor Only the upper triangle of the [count,count] uint32 result is guaranteed to be initialized.
Returns a new Tensor, or out when given.
vectors_BufferType | Input matrix of shape [count,depth], with 'uint1' bits packed into uint8 bytes. | |
|---|---|---|
dtypeLiteral['uint1', 'int4', 'uint4', 'int64', 'int32', 'int16', 'int8', 'uint64', 'uint32', 'uint16', 'uint8'] | _MiniFloatType | None | Input dtype to read vectors as, overriding the one it reports. | |
out_BufferType | None | C-contiguous [count,count] output of dtype uint32. | |
rows_beginint | None | First row to compute, 0 when None. | |
rows_endint | None | One past the last row to compute, count when None; only the upper triangle
overlapping the rows in range is filled. | |
threadsint | Worker threads. | |
capabilitiesCapability | int | None | Capabilities to run within: every CPU one by default, or for packed operands the mask that packed them. | |
streamint | None | A GPU stream pointer, left None on the CPU. |
jaccards_symmetricCompute the symmetric all-pairs Jaccard-distance matrix of the rows of vectors.def jaccards_symmetric(
vectors: _BufferType,
/,
*,
dtype: Literal['uint1', 'int4', 'uint4', 'int64', 'int32', 'int16', 'int8', 'uint64', 'uint32', 'uint16', 'uint8'] | _MiniFloatType | None = None,
out: _BufferType | None = None,
rows_begin: int | None = None,
rows_end: int | None = None,
threads: int = 1,
capabilities: Capability | int | None = ...,
stream: int | None = ...,
) -> Tensor Only the upper triangle of the [count,count] result is guaranteed to be initialized. Returns a
new Tensor, or out when given.
vectors_BufferType | Input matrix of shape [count,depth], with 'uint1' bits packed into uint8 bytes. | |
|---|---|---|
dtypeLiteral['uint1', 'int4', 'uint4', 'int64', 'int32', 'int16', 'int8', 'uint64', 'uint32', 'uint16', 'uint8'] | _MiniFloatType | None | Input dtype to read vectors as, overriding the one it reports. | |
out_BufferType | None | C-contiguous [count,count] output. | |
rows_beginint | None | First row to compute, 0 when None. | |
rows_endint | None | One past the last row to compute, count when None; only the upper triangle
overlapping the rows in range is filled. | |
threadsint | Worker threads. | |
capabilitiesCapability | int | None | Capabilities to run within: every CPU one by default, or for packed operands the mask that packed them. | |
streamint | None | A GPU stream pointer, left None on the CPU. |
angulars_symmetricCompute the symmetric all-pairs angular-distance matrix of the rows of vectors.def angulars_symmetric(
vectors: _BufferType,
/,
*,
dtype: _FloatTypeName | Literal['uint1', 'int4', 'uint4', 'int64', 'int32', 'int16', 'int8', 'uint64', 'uint32', 'uint16', 'uint8'] | _MiniFloatType | None = None,
out: _BufferType | None = None,
rows_begin: int | None = None,
rows_end: int | None = None,
threads: int = 1,
capabilities: Capability | int | None = ...,
stream: int | None = ...,
) -> Tensor Only the upper triangle of the [count,count] result is guaranteed to be initialized. Returns a
new Tensor, or out when given. On a GPU the call returns before the kernel finishes.
vectors_BufferType | Input matrix of shape [count,depth], or a CUDA or ROCm Tensor from from_dlpack() to run on that GPU. | |
|---|---|---|
dtype_FloatTypeName | Literal['uint1', 'int4', 'uint4', 'int64', 'int32', 'int16', 'int8', 'uint64', 'uint32', 'uint16', 'uint8'] | _MiniFloatType | None | Input dtype to read vectors as, overriding the one it reports. | |
out_BufferType | None | C-contiguous [count,count] output, required on the same GPU for GPU vectors. | |
rows_beginint | None | First row to compute, 0 when None. | |
rows_endint | None | One past the last row to compute, count when None; only the upper triangle
overlapping the rows in range is filled. | |
threadsint | Worker threads, ignored on a GPU. | |
capabilitiesCapability | int | None | Capabilities to run within: every CPU one by default, or for packed operands the mask that packed them. | |
streamint | None | A GPU stream pointer, left None on the CPU. |
euclideans_symmetricCompute the symmetric all-pairs Euclidean-distance matrix of the rows of vectors.def euclideans_symmetric(
vectors: _BufferType,
/,
*,
dtype: _FloatTypeName | Literal['uint1', 'int4', 'uint4', 'int64', 'int32', 'int16', 'int8', 'uint64', 'uint32', 'uint16', 'uint8'] | _MiniFloatType | None = None,
out: _BufferType | None = None,
rows_begin: int | None = None,
rows_end: int | None = None,
threads: int = 1,
capabilities: Capability | int | None = ...,
stream: int | None = ...,
) -> Tensor Only the upper triangle of the [count,count] result is guaranteed to be initialized. Returns a
new Tensor, or out when given. On a GPU the call returns before the kernel finishes.
vectors_BufferType | Input matrix of shape [count,depth], or a CUDA or ROCm Tensor from from_dlpack() to run on that GPU. | |
|---|---|---|
dtype_FloatTypeName | Literal['uint1', 'int4', 'uint4', 'int64', 'int32', 'int16', 'int8', 'uint64', 'uint32', 'uint16', 'uint8'] | _MiniFloatType | None | Input dtype to read vectors as, overriding the one it reports. | |
out_BufferType | None | C-contiguous [count,count] output, required on the same GPU for GPU vectors. | |
rows_beginint | None | First row to compute, 0 when None. | |
rows_endint | None | One past the last row to compute, count when None; only the upper triangle
overlapping the rows in range is filled. | |
threadsint | Worker threads, ignored on a GPU. | |
capabilitiesCapability | int | None | Capabilities to run within: every CPU one by default, or for packed operands the mask that packed them. | |
streamint | None | A GPU stream pointer, left None on the CPU. |
dots_packPack a matrix with contiguous rows for repeated dot-product cross operations.def dots_pack(
b: _BufferType,
/,
dtype: Literal['uint1', 'int4', 'uint4', 'int64', 'int32', 'int16', 'int8', 'uint64', 'uint32', 'uint16', 'uint8'] | _FloatTypeName | _ComplexTypeName | _MiniFloatType | None = None,
*,
out: _BufferType | None = None,
threads: int = 1,
capabilities: Capability | int | None = ...,
stream: int | None = ...,
) -> PackedMatrix Packing fuses no transposition, so transpose w.T into a contiguous copy first. The pack serves
dots_packed(), angulars_packed(), euclideans_packed() and the @ operator of Tensor.
b_BufferType | Source matrix of shape [columns,depth], or a CUDA or ROCm Tensor from from_dlpack() to pack on that GPU. | |
|---|---|---|
dtypeLiteral['uint1', 'int4', 'uint4', 'int64', 'int32', 'int16', 'int8', 'uint64', 'uint32', 'uint16', 'uint8'] | _FloatTypeName | _ComplexTypeName | _MiniFloatType | None | Packing dtype, inferred from b when None. | |
out_BufferType | None | C-contiguous Tensor on the GPU of b holding the pack, required for a GPU b, of at
least PackedMatrix.pack_size() bytes. | |
threadsint | Worker threads, ignored on a GPU. | |
capabilitiesCapability | int | None | Capabilities to run within: every CPU one by default, or for packed operands the mask that packed them. | |
streamint | None | A GPU stream pointer, left None on the CPU. |
dots_packedCompute dot products between rows of a and a matrix packed by dots_pack(), like a @ b.T.def dots_packed(
a: _BufferType,
b: PackedMatrix,
/,
*,
out: _BufferType | None = None,
rows_begin: int | None = None,
rows_end: int | None = None,
threads: int = 1,
capabilities: Capability | int | None = ...,
stream: int | None = ...,
) -> Tensor Returns a [rows,columns] Tensor, or out when given. On a GPU the call returns before the
kernel finishes.
a_BufferType | Query matrix of shape [rows,depth], on the device of b. | |
|---|---|---|
bPackedMatrix | Matrix packed by dots_pack(), of shape [columns,depth]. | |
out_BufferType | None | C-contiguous [rows,columns] output, required on the same GPU for a GPU-packed b. | |
rows_beginint | None | First row of a to process, 0 when None. | |
rows_endint | None | One past the last row of a to process, every row when None. | |
threadsint | Worker threads, ignored on a GPU. | |
capabilitiesCapability | int | None | Capabilities to run within: every CPU one by default, or for packed operands the mask that packed them. | |
streamint | None | A GPU stream pointer, left None on the CPU. |
hammings_packPack a matrix for repeated Hamming and Jaccard cross operations.def hammings_pack(
b: _BufferType,
/,
dtype: Literal['uint1', 'int4', 'uint4', 'int64', 'int32', 'int16', 'int8', 'uint64', 'uint32', 'uint16', 'uint8'] | _FloatTypeName | _ComplexTypeName | _MiniFloatType | None = None,
*,
threads: int = 1,
capabilities: Capability | int | None = ...,
stream: int | None = ...,
) -> PackedMatrix The pack serves hammings_packed() and jaccards_packed().
b_BufferType | Source matrix of shape [columns,depth], with 'uint1' bits packed into uint8 bytes. | |
|---|---|---|
dtypeLiteral['uint1', 'int4', 'uint4', 'int64', 'int32', 'int16', 'int8', 'uint64', 'uint32', 'uint16', 'uint8'] | _FloatTypeName | _ComplexTypeName | _MiniFloatType | None | Packing dtype, 'uint1' when None. | |
threadsint | Worker threads. | |
capabilitiesCapability | int | None | Capabilities to run within: every CPU one by default, or for packed operands the mask that packed them. | |
streamint | None | A GPU stream pointer, left None on the CPU. |
hammings_packedCompute Hamming distances between rows of a and a matrix packed by hammings_pack().def hammings_packed(
a: _BufferType,
b: PackedMatrix,
/,
*,
out: _BufferType | None = None,
rows_begin: int | None = None,
rows_end: int | None = None,
threads: int = 1,
capabilities: Capability | int | None = ...,
stream: int | None = ...,
) -> Tensor Returns a [rows,columns] uint32 Tensor, or out when given.
a_BufferType | Query matrix of shape [rows,depth]. | |
|---|---|---|
bPackedMatrix | Matrix packed by hammings_pack(), of shape [columns,depth]. | |
out_BufferType | None | C-contiguous [rows,columns] output of dtype uint32. | |
rows_beginint | None | First row of a to process, 0 when None. | |
rows_endint | None | One past the last row of a to process, every row when None. | |
threadsint | Worker threads. | |
capabilitiesCapability | int | None | Capabilities to run within: every CPU one by default, or for packed operands the mask that packed them. | |
streamint | None | A GPU stream pointer, left None on the CPU. |
jaccards_packedCompute Jaccard distances between rows of a and a matrix packed by hammings_pack().def jaccards_packed(
a: _BufferType,
b: PackedMatrix,
/,
*,
out: _BufferType | None = None,
rows_begin: int | None = None,
rows_end: int | None = None,
threads: int = 1,
capabilities: Capability | int | None = ...,
stream: int | None = ...,
) -> Tensor Returns a [rows,columns] Tensor, or out when given.
a_BufferType | Query matrix of shape [rows,depth]. | |
|---|---|---|
bPackedMatrix | Matrix packed by hammings_pack(), of shape [columns,depth]. | |
out_BufferType | None | C-contiguous [rows,columns] output. | |
rows_beginint | None | First row of a to process, 0 when None. | |
rows_endint | None | One past the last row of a to process, every row when None. | |
threadsint | Worker threads. | |
capabilitiesCapability | int | None | Capabilities to run within: every CPU one by default, or for packed operands the mask that packed them. | |
streamint | None | A GPU stream pointer, left None on the CPU. |
angulars_packedCompute angular distances between rows of a and a matrix packed by dots_pack().def angulars_packed(
a: _BufferType,
b: PackedMatrix,
/,
*,
out: _BufferType | None = None,
rows_begin: int | None = None,
rows_end: int | None = None,
threads: int = 1,
capabilities: Capability | int | None = ...,
stream: int | None = ...,
) -> Tensor Returns a [rows,columns] Tensor, or out when given. On a GPU the call returns before the
kernel finishes.
a_BufferType | Query matrix of shape [rows,depth], on the device of b. | |
|---|---|---|
bPackedMatrix | Matrix packed by dots_pack(), of shape [columns,depth]. | |
out_BufferType | None | C-contiguous [rows,columns] output, required on the same GPU for a GPU-packed b. | |
rows_beginint | None | First row of a to process, 0 when None. | |
rows_endint | None | One past the last row of a to process, every row when None. | |
threadsint | Worker threads, ignored on a GPU. | |
capabilitiesCapability | int | None | Capabilities to run within: every CPU one by default, or for packed operands the mask that packed them. | |
streamint | None | A GPU stream pointer, left None on the CPU. |
euclideans_packedCompute Euclidean distances between rows of a and a matrix packed by dots_pack().def euclideans_packed(
a: _BufferType,
b: PackedMatrix,
/,
*,
out: _BufferType | None = None,
rows_begin: int | None = None,
rows_end: int | None = None,
threads: int = 1,
capabilities: Capability | int | None = ...,
stream: int | None = ...,
) -> Tensor Returns a [rows,columns] Tensor, or out when given. On a GPU the call returns before the
kernel finishes.
a_BufferType | Query matrix of shape [rows,depth], on the device of b. | |
|---|---|---|
bPackedMatrix | Matrix packed by dots_pack(), of shape [columns,depth]. | |
out_BufferType | None | C-contiguous [rows,columns] output, required on the same GPU for a GPU-packed b. | |
rows_beginint | None | First row of a to process, 0 when None. | |
rows_endint | None | One past the last row of a to process, every row when None. | |
threadsint | Worker threads, ignored on a GPU. | |
capabilitiesCapability | int | None | Capabilities to run within: every CPU one by default, or for packed operands the mask that packed them. | |
streamint | None | A GPU stream pointer, left None on the CPU. |
attention_packPack ragged K/V token matrices into a backend-opaque KV-cache blob.def attention_pack(
k: _BufferType,
v: _BufferType,
/,
key_offsets: _BufferType,
key_lengths: _BufferType | None = None,
depth: int | None = None,
out: Tensor | None = None,
threads: int = 1,
*,
capabilities: Capability | int | None = ...,
stream: int | None = ...,
) -> AttentionPackedMatrix Segment s keeps its key_lengths[s] keys, by default the whole slot, from row
key_offsets[s].
capabilitiesCapability | int | None | Capabilities to run within: every CPU one by default, or for packed operands the mask that packed them. | |
|---|---|---|
streamint | None | A GPU stream pointer, left None on the CPU. |
attention_packedRagged scaled-dot-product attention against a pre-packed KV-cache, under a band of keys.def attention_packed(
q: _BufferType,
kv: AttentionPackedMatrix,
/,
query_offsets: _BufferType,
out: Tensor | None = None,
scale: float | None = None,
keys_before: int | None = None,
keys_after: int | None = None,
log_sum_exp: _BufferType | None = None,
threads: int = 1,
*,
capabilities: Capability | int | None = ...,
stream: int | None = ...,
) -> Tensor Query row r of q queries over k keys sees the keys from r + k - q - keys_before through
r + k - q + keys_after, each side unbounded at None.
capabilitiesCapability | int | None | Capabilities to run within: every CPU one by default, or for packed operands the mask that packed them. | |
|---|---|---|
streamint | None | A GPU stream pointer, left None on the CPU. |
attention_packed_gradientsCompute the bf16 query, key and value gradients of attention_packed under the same band.def attention_packed_gradients(
q: _BufferType,
kv: AttentionPackedMatrix,
/,
query_offsets: _BufferType,
output: _BufferType,
output_gradient: _BufferType,
log_sum_exp: _BufferType,
scale: float | None = None,
keys_before: int | None = None,
keys_after: int | None = None,
query_gradient: Tensor | None = None,
threads: int = 1,
*,
capabilities: Capability | int | None = ...,
stream: int | None = ...,
) -> tuple[Tensor, Tensor, Tensor] capabilitiesCapability | int | None | Capabilities to run within: every CPU one by default, or for packed operands the mask that packed them. | |
|---|---|---|
streamint | None | A GPU stream pointer, left None on the CPU. |
attention_ropeRotate every channel pair of each head by the per-token angle grids, in place unless out is given.def attention_rope(
x: _BufferType,
cos: _BufferType,
sin: _BufferType,
/,
head_count: int,
depth: int,
*,
out: _BufferType | None = None,
capabilities: Capability | int | None = ...,
stream: int | None = ...,
) -> None x_BufferType | [rows,head_count*depth], float32, bfloat16, or e4m3. | |
|---|---|---|
cos_BufferType | [rows,depth/2] float32 angle grid, shared across heads. | |
sin_BufferType | [rows,depth/2] float32 angle grid, shared across heads. | |
head_countint | Number of heads per token. | |
depthint | Even number of channels per head. | |
out_BufferType | None | Output, same shape and dtype as x, may alias x, defaulting to x. | |
capabilitiesCapability | int | None | Capabilities to run within: every CPU one by default, or for packed operands the mask that packed them. | |
streamint | None | A GPU stream pointer, left None on the CPU. |