Use BF16 state at every CUDA batch and stabilize physical-ring attention
#1
by hkust-aaron - opened
- docs/runtime.md +27 -10
- modeling_edgerock.py +1 -1
- runtime/inference.py +0 -3
- runtime/model/inference_kernels.py +16 -5
- runtime/optimizations/SOURCE.json +82 -2
- runtime/optimizations/b1_bf16_selected.py +2 -2
docs/runtime.md
CHANGED
|
@@ -1,14 +1,14 @@
|
|
| 1 |
# EdgeRock-4B inference runtime and results
|
| 2 |
|
| 3 |
-
|
| 4 |
|
| 5 |
-
##
|
| 6 |
|
| 7 |
-
| Component |
|
| 8 |
| --- | --- |
|
| 9 |
| All model weights, including MLP and output head | BF16, unquantized |
|
| 10 |
| Local and anchor KV | BF16 |
|
| 11 |
-
| GDN recurrent-state storage |
|
| 12 |
| GDN state updates | FP32 |
|
| 13 |
| Local attention window | 1,024 positions |
|
| 14 |
| Committed anchor capacity | 1,024 records per KV group |
|
|
@@ -18,15 +18,17 @@ EdgeRock-4B sustains 233.7 decode tokens/s at batch size 1 with 128K input and 1
|
|
| 18 |
|
| 19 |
## Constant-size persistent history
|
| 20 |
|
| 21 |
-
EdgeRock-4B maintains 97.76 MiB of persistent history per sequence,
|
| 22 |
|
| 23 |
## Optimized execution
|
| 24 |
|
| 25 |
-
The `fast` CUDA profile retains the report's
|
| 26 |
|
| 27 |
-
|
| 28 |
|
| 29 |
-
|
|
|
|
|
|
|
| 30 |
|
| 31 |
## Throughput definitions
|
| 32 |
|
|
@@ -36,7 +38,20 @@ The fixed-length batch-size-1 benchmark additionally uses the validated output-h
|
|
| 36 |
|
| 37 |
Loading, warmup, tokenization, and text decoding are excluded from both throughput measures. `1K = 1,024` tokens.
|
| 38 |
|
| 39 |
-
##
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 40 |
|
| 41 |
Single-request sustained decoding uses 128K input and 128K output. The native-context boundary check uses 254K input and 2K output; both total 262,144 tokens. The long-generation grid combines input and output lengths in {4K, 8K, 16K, 32K}, at batch sizes 32, 64, 128, 256, 320, 384, and 512. The short grid uses 4K input and 2K output at batch sizes 1, 2, 4, 8, 16, 32, 64, 128, 256, 320, 384, and 512.
|
| 42 |
|
|
@@ -44,7 +59,9 @@ Each EdgeRock configuration has three independent runs. Per-workload results use
|
|
| 44 |
|
| 45 |
The benchmark uses synthetic tokens, a separate 256-token warmup, EOS disabled, temperature 1.0, top-k 20, top-p 0.95, and presence penalty 1.5. Eight continuations share each prompt in the batch grid and then retain independent histories. Batch size denotes submitted requests; EdgeRock maintains target concurrency, while vLLM schedules within its cache budget.
|
| 46 |
|
| 47 |
-
##
|
|
|
|
|
|
|
| 48 |
|
| 49 |
The following tables report fixed-length performance on one Hopper 80GB GPU with BF16 weights and KV, FP32 GDN updates, and tensor-parallel size one. Recurrent-state storage is FP32 at batch size 1 and FP16 for larger batches.
|
| 50 |
|
|
|
|
| 1 |
# EdgeRock-4B inference runtime and results
|
| 2 |
|
| 3 |
+
The [technical report](report/EdgeRock_Technical_Report.pdf) records historical measurements of 233.7 decode tokens/s at batch size 1 with 128K input and 128K output, and 12,124 end-to-end output tokens/s at batch size 512 with 32K input and 32K output, on one Hopper 80GB GPU. Those measurements predate the all-batch BF16-state and attention changes in this release. The current Runtime qualification is reported separately below.
|
| 4 |
|
| 5 |
+
## Runtime precision and history contract
|
| 6 |
|
| 7 |
+
| Component | CUDA runtime |
|
| 8 |
| --- | --- |
|
| 9 |
| All model weights, including MLP and output head | BF16, unquantized |
|
| 10 |
| Local and anchor KV | BF16 |
|
| 11 |
+
| GDN recurrent-state storage | BF16 at every batch size |
|
| 12 |
| GDN state updates | FP32 |
|
| 13 |
| Local attention window | 1,024 positions |
|
| 14 |
| Committed anchor capacity | 1,024 records per KV group |
|
|
|
|
| 18 |
|
| 19 |
## Constant-size persistent history
|
| 20 |
|
| 21 |
+
EdgeRock-4B maintains 97.76 MiB of persistent history per sequence, including BF16 recurrent matrices and auxiliary tensors, independently of sequence length. The configuration-derived attention-KV capacity is 72 MiB. During decode, the local ring stores 1,023 preceding positions while the current token is supplied by the decoder, so the audited local-plus-anchor KV payload is 71.97 MiB. Full device allocation also includes weights, buffers, graphs, and workspace.
|
| 22 |
|
| 23 |
## Optimized execution
|
| 24 |
|
| 25 |
+
The `fast` CUDA profile uses BF16 recurrent-state storage and retains the report's FP32 state-update accumulation and cache capacities. Its selected implementation combines BF16 projection and normalization fusions, joint memory projection, cross-layer residual/RMSNorm fusion, local-attention Q/K preparation, and CUDA Graph replay. At batch size 512, original projection parameters share byte-identical storage with packed BF16 weights, removing 4.95 GiB of duplicate allocation.
|
| 26 |
|
| 27 |
+
Physical-ring decode attention uses PyTorch `EFFICIENT_ATTENTION` with grouped query heads and views of the existing KV storage within each request. Independent requests keep separate caches. This avoids the cuDNN SDPA forward nondeterminism observed in the validated environment, without duplicating persistent KV. The frozen report measurements below predate this attention change; new Runtime throughput must be measured separately.
|
| 28 |
|
| 29 |
+
The fixed-length batch-size-1 benchmark additionally uses the validated output-head/sampling-state fusion. That path is restricted to its tested sampling contract: temperature 1.0, top-k 20, top-p 0.95, EOS disabled, no streaming or resumed prefill. General generation retains EOS, configurable sampling, and request-stream handling through the native generator. Both use BF16 weights/KV and FP32 GDN updates. All batch sizes store recurrent state in BF16.
|
| 30 |
+
|
| 31 |
+
`reference` retains the reference local-attention execution path. It also uses unquantized weights, BF16 recurrent-state storage and FP32 state-update accumulation. It is a correctness-oriented execution profile, not the report's throughput configuration.
|
| 32 |
|
| 33 |
## Throughput definitions
|
| 34 |
|
|
|
|
| 38 |
|
| 39 |
Loading, warmup, tokenization, and text decoding are excluded from both throughput measures. `1K = 1,024` tokens.
|
| 40 |
|
| 41 |
+
## Current Runtime qualification (2026-10-18)
|
| 42 |
+
|
| 43 |
+
On one H800, with PyTorch 2.11.0+cu130 and cuDNN 91900, the released source passed two independent reference/release process pairs at both B1 and B512. Generated tokens matched across implementations and within each implementation's repeats. Actual BF16 prefill/decode storage, independent per-request prefill, cache bytes, and the original peak-memory tolerance also passed. The release ran without an SDPA wrapper; the frozen reference used an external correction to the same grouped efficient-attention backend. This establishes equivalence under that common backend, not bitwise equivalence to historical cuDNN outputs.
|
| 44 |
+
|
| 45 |
+
The speed comparison below uses 4K input plus 2K output per request, BF16 weights/KV/recurrent storage, FP32 state updates, no quantization/speculation/offload, and no prefix caching or cross-request reuse. Each implementation completed one full-generation warmup followed by three timed generations. Output TPS includes independent prefill and excludes loading and warmup. The baseline is the original default frozen runtime; the release includes the attention correction.
|
| 46 |
+
|
| 47 |
+
| Batch | Original default output TPS, three trials | Released output TPS, three trials | Original median | Released median | Change | Peak allocated GiB, both |
|
| 48 |
+
| ---: | --- | --- | ---: | ---: | ---: | ---: |
|
| 49 |
+
| 1 | 230.410 / 230.385 / 219.525 | 210.746 / 210.726 / 203.972 | 230.385 | 210.726 | −8.53% | 14.270 |
|
| 50 |
+
| 512 | 8270.370 / 8272.755 / 8233.773 | 8218.094 / 8217.190 / 8168.149 | 8270.370 | 8217.190 | −0.64% | 63.548 |
|
| 51 |
+
|
| 52 |
+
The released implementation produced identical token hashes in all three timed repetitions at each batch. Cache bytes and peak allocation did not increase. These measurements document the performance cost of the attention correction; they are Runtime qualification results and do not replace the frozen report tables or the separate BF16 paper rerun. They are output TPS, not decode-only rates. Acceptance run `edgerock-bf16-runtime-acceptance-20261018-v17`, artifact hashes, and exact measurements are recorded in [SOURCE.json](../runtime/optimizations/SOURCE.json).
|
| 53 |
+
|
| 54 |
+
## Historical report workloads
|
| 55 |
|
| 56 |
Single-request sustained decoding uses 128K input and 128K output. The native-context boundary check uses 254K input and 2K output; both total 262,144 tokens. The long-generation grid combines input and output lengths in {4K, 8K, 16K, 32K}, at batch sizes 32, 64, 128, 256, 320, 384, and 512. The short grid uses 4K input and 2K output at batch sizes 1, 2, 4, 8, 16, 32, 64, 128, 256, 320, 384, and 512.
|
| 57 |
|
|
|
|
| 59 |
|
| 60 |
The benchmark uses synthetic tokens, a separate 256-token warmup, EOS disabled, temperature 1.0, top-k 20, top-p 0.95, and presence penalty 1.5. Eight continuations share each prompt in the batch grid and then retain independent histories. Batch size denotes submitted requests; EdgeRock maintains target concurrency, while vLLM schedules within its cache budget.
|
| 61 |
|
| 62 |
+
## Historical report measurements
|
| 63 |
+
|
| 64 |
+
These are the published report measurements. The BF16-state rerun is in progress; these tables have not yet been replaced with its results.
|
| 65 |
|
| 66 |
The following tables report fixed-length performance on one Hopper 80GB GPU with BF16 weights and KV, FP32 GDN updates, and tensor-parallel size one. Recurrent-state storage is FP32 at batch size 1 and FP16 for larger batches.
|
| 67 |
|
modeling_edgerock.py
CHANGED
|
@@ -706,7 +706,7 @@ class FixedMemoryHybridDynamicCache(Cache):
|
|
| 706 |
if index in swa_layers:
|
| 707 |
layers.append(FixedMemorySlidingWindowLayer(window))
|
| 708 |
elif layer_type == 'linear_attention':
|
| 709 |
-
prefill_dtype = torch.bfloat16 if getattr(text_config, 'gdn_recurrent_state_storage', 'fp32')
|
| 710 |
layers.append(FixedMemoryLinearAttentionLayer(recurrent_prefill_dtype=prefill_dtype))
|
| 711 |
else:
|
| 712 |
raise ValueError(f'unsupported fixed-memory cache layer {index}: {layer_type}')
|
|
|
|
| 706 |
if index in swa_layers:
|
| 707 |
layers.append(FixedMemorySlidingWindowLayer(window))
|
| 708 |
elif layer_type == 'linear_attention':
|
| 709 |
+
prefill_dtype = torch.bfloat16 if getattr(text_config, 'gdn_recurrent_state_storage', 'fp32') in {'bf16_non_anchor', 'fp16_non_anchor'} else None
|
| 710 |
layers.append(FixedMemoryLinearAttentionLayer(recurrent_prefill_dtype=prefill_dtype))
|
| 711 |
else:
|
| 712 |
raise ValueError(f'unsupported fixed-memory cache layer {index}: {layer_type}')
|
runtime/inference.py
CHANGED
|
@@ -70,9 +70,6 @@ class Engine:
|
|
| 70 |
self.operators['shared_bf16_weight_bytes'] = sharing['saved_bytes']
|
| 71 |
self.operators['bitwise_weight_checks'] = sharing['bitwise_weight_checks']
|
| 72 |
self.operators['selected_bf16_fusions'] = True
|
| 73 |
-
if batch > 1:
|
| 74 |
-
self.model.config.gdn_recurrent_state_storage = 'fp16_non_anchor'
|
| 75 |
-
self.operators['gdn_recurrent_state_storage'] = 'fp16_non_anchor'
|
| 76 |
else:
|
| 77 |
from model.fixed_memory import load_model
|
| 78 |
self.model = load_model(model, backend='torch', torch_dtype=dtype,
|
|
|
|
| 70 |
self.operators['shared_bf16_weight_bytes'] = sharing['saved_bytes']
|
| 71 |
self.operators['bitwise_weight_checks'] = sharing['bitwise_weight_checks']
|
| 72 |
self.operators['selected_bf16_fusions'] = True
|
|
|
|
|
|
|
|
|
|
| 73 |
else:
|
| 74 |
from model.fixed_memory import load_model
|
| 75 |
self.model = load_model(model, backend='torch', torch_dtype=dtype,
|
runtime/model/inference_kernels.py
CHANGED
|
@@ -3,7 +3,6 @@
|
|
| 3 |
# Licensed under Apache-2.0: https://www.apache.org/licenses/LICENSE-2.0
|
| 4 |
from __future__ import annotations
|
| 5 |
from dataclasses import dataclass
|
| 6 |
-
from contextlib import nullcontext
|
| 7 |
import torch
|
| 8 |
from torch import Tensor
|
| 9 |
import importlib
|
|
@@ -985,7 +984,7 @@ def enable_bf16_b1_lm_head_inference(model: torch.nn.Module) -> int:
|
|
| 985 |
|
| 986 |
def install_inference(model) -> dict[str, int | str | bool]:
|
| 987 |
gdn_bv, gdn_warps = (128, 4)
|
| 988 |
-
recurrent_storage = '
|
| 989 |
stack = {'fixed_memory_operator_profile': 'max_throughput', 'operator_revision': 'independent-gqa-grouped-fused-decode-v6', 'memory_backend': 'triton_direct_indexed_gqa', 'memory_decode_backend': 'triton_committed_gqa_masked_commit', 'memory_cache_dtype': 'bfloat16', 'packed_memory_layers': enable_independent_memory_packed_projections(model), 'packed_mlp_layers': enable_packed_mlp_inference(model), 'fused_mlp_activation_layers': enable_fused_mlp_activation_inference(model), 'packed_native_gdn_layers': enable_packed_all_native_gdn_inference(model), 'packed_all_native_gdn': True, 'graph_safe_conv_layers': enable_triton_graph_safe_conv_update(model), 'packed_swa_projection_layers': enable_packed_swa_projection_inference(model), 'native_rmsnorm_layers': enable_native_rmsnorm_inference(model, torch_tree=True), 'rmsnorm_reduction': 'torch_fp32_tree_fused', 'fused_residual_rmsnorm_layers': enable_fused_residual_rmsnorm_inference(model), 'fused_swa_output_gate_layers': enable_fused_swa_output_gate_inference(model), 'inplace_native_gdn_state': enable_inplace_native_gdn_state_inference(gdn_bv, gdn_warps, adaptive=True), 'gdn_block_value': gdn_bv, 'gdn_num_warps': gdn_warps, 'gdn_small_batch_block_value': 32, 'fused_gdn_gate_layers': enable_fused_gdn_gate_inference(model, grouped_query=True), 'gdn_grouped_query_decode': True, 'physical_ring_swa_layers': enable_physical_ring_fixed_memory_swa_update(model), 'swa_backend': 'physical', 'gdn_recurrent_state_storage': recurrent_storage, 'fused_decode_state': True, 'bf16_b1_lm_head': enable_bf16_b1_lm_head_inference(model)}
|
| 990 |
model.config.fixed_memory_operator_profile = 'max_throughput'
|
| 991 |
model.config.fixed_memory_operator_revision = stack['operator_revision']
|
|
@@ -1793,9 +1792,21 @@ def fixed_memory_physical_ring_decode_attention(query: torch.Tensor, ring_key: t
|
|
| 1793 |
if query_heads % key_heads:
|
| 1794 |
raise ValueError('query heads must be a multiple of physical-ring KV heads')
|
| 1795 |
from torch.nn.attention import SDPBackend, sdpa_kernel
|
| 1796 |
-
|
| 1797 |
-
|
| 1798 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1799 |
|
| 1800 |
@triton.jit
|
| 1801 |
def _qwen35_sigmoid_mul_kernel(values_ptr, gate_ptr, output_ptr, total_elements: tl.constexpr, block_size: tl.constexpr):
|
|
|
|
| 3 |
# Licensed under Apache-2.0: https://www.apache.org/licenses/LICENSE-2.0
|
| 4 |
from __future__ import annotations
|
| 5 |
from dataclasses import dataclass
|
|
|
|
| 6 |
import torch
|
| 7 |
from torch import Tensor
|
| 8 |
import importlib
|
|
|
|
| 984 |
|
| 985 |
def install_inference(model) -> dict[str, int | str | bool]:
|
| 986 |
gdn_bv, gdn_warps = (128, 4)
|
| 987 |
+
recurrent_storage = 'bf16_non_anchor'
|
| 988 |
stack = {'fixed_memory_operator_profile': 'max_throughput', 'operator_revision': 'independent-gqa-grouped-fused-decode-v6', 'memory_backend': 'triton_direct_indexed_gqa', 'memory_decode_backend': 'triton_committed_gqa_masked_commit', 'memory_cache_dtype': 'bfloat16', 'packed_memory_layers': enable_independent_memory_packed_projections(model), 'packed_mlp_layers': enable_packed_mlp_inference(model), 'fused_mlp_activation_layers': enable_fused_mlp_activation_inference(model), 'packed_native_gdn_layers': enable_packed_all_native_gdn_inference(model), 'packed_all_native_gdn': True, 'graph_safe_conv_layers': enable_triton_graph_safe_conv_update(model), 'packed_swa_projection_layers': enable_packed_swa_projection_inference(model), 'native_rmsnorm_layers': enable_native_rmsnorm_inference(model, torch_tree=True), 'rmsnorm_reduction': 'torch_fp32_tree_fused', 'fused_residual_rmsnorm_layers': enable_fused_residual_rmsnorm_inference(model), 'fused_swa_output_gate_layers': enable_fused_swa_output_gate_inference(model), 'inplace_native_gdn_state': enable_inplace_native_gdn_state_inference(gdn_bv, gdn_warps, adaptive=True), 'gdn_block_value': gdn_bv, 'gdn_num_warps': gdn_warps, 'gdn_small_batch_block_value': 32, 'fused_gdn_gate_layers': enable_fused_gdn_gate_inference(model, grouped_query=True), 'gdn_grouped_query_decode': True, 'physical_ring_swa_layers': enable_physical_ring_fixed_memory_swa_update(model), 'swa_backend': 'physical', 'gdn_recurrent_state_storage': recurrent_storage, 'fused_decode_state': True, 'bf16_b1_lm_head': enable_bf16_b1_lm_head_inference(model)}
|
| 989 |
model.config.fixed_memory_operator_profile = 'max_throughput'
|
| 990 |
model.config.fixed_memory_operator_revision = stack['operator_revision']
|
|
|
|
| 1792 |
if query_heads % key_heads:
|
| 1793 |
raise ValueError('query heads must be a multiple of physical-ring KV heads')
|
| 1794 |
from torch.nn.attention import SDPBackend, sdpa_kernel
|
| 1795 |
+
if reproducible:
|
| 1796 |
+
with sdpa_kernel(SDPBackend.MATH):
|
| 1797 |
+
output = F.scaled_dot_product_attention(query.transpose(1, 2), ring_key, ring_value, attn_mask=valid[:, None, None, :], dropout_p=0.0, is_causal=False, enable_gqa=query_heads != key_heads)
|
| 1798 |
+
return output.transpose(1, 2)
|
| 1799 |
+
batch = int(query.shape[0])
|
| 1800 |
+
groups = query_heads // key_heads
|
| 1801 |
+
window = int(ring_key.shape[2])
|
| 1802 |
+
# Zero-stride head views preserve GQA without copying KV or selecting cuDNN.
|
| 1803 |
+
q = query.transpose(1, 2).reshape(batch * key_heads, groups, 1, query.shape[-1])
|
| 1804 |
+
k = ring_key.reshape(batch * key_heads, 1, window, ring_key.shape[-1]).expand(-1, groups, -1, -1)
|
| 1805 |
+
v = ring_value.reshape(batch * key_heads, 1, window, ring_value.shape[-1]).expand(-1, groups, -1, -1)
|
| 1806 |
+
mask = valid[:, None, :].expand(-1, key_heads, -1).reshape(batch * key_heads, 1, 1, window)
|
| 1807 |
+
with sdpa_kernel(SDPBackend.EFFICIENT_ATTENTION):
|
| 1808 |
+
output = F.scaled_dot_product_attention(q, k, v, attn_mask=mask, dropout_p=0.0, is_causal=False)
|
| 1809 |
+
return output.reshape(batch, query_heads, 1, ring_value.shape[-1]).transpose(1, 2)
|
| 1810 |
|
| 1811 |
@triton.jit
|
| 1812 |
def _qwen35_sigmoid_mul_kernel(values_ptr, gate_ptr, output_ptr, total_elements: tl.constexpr, block_size: tl.constexpr):
|
runtime/optimizations/SOURCE.json
CHANGED
|
@@ -4,12 +4,14 @@
|
|
| 4 |
"source": "Frozen implementation used for the October 2026 technical report",
|
| 5 |
"packaging_changes": [
|
| 6 |
"Package-relative imports.",
|
| 7 |
-
"
|
|
|
|
|
|
|
| 8 |
],
|
| 9 |
"components": {
|
| 10 |
"b1_bf16_selected.py": {
|
| 11 |
"report_source_sha256": "82d7484627684ed3c2375a8d0339497399e67cf24ae705cddb45215cfe75f57d",
|
| 12 |
-
"release_sha256": "
|
| 13 |
},
|
| 14 |
"b1_bf16_fusions.py": {
|
| 15 |
"report_source_sha256": "9cd816ae32ee03e312445291dd859ff41b43acee94ee916de1e213db98d11a9b",
|
|
@@ -39,5 +41,83 @@
|
|
| 39 |
"report_source_sha256": "02677ef9d025423264c6b4a9bfaf85c82d5675aa74bf07de51d787f0699d9345",
|
| 40 |
"release_sha256": "02677ef9d025423264c6b4a9bfaf85c82d5675aa74bf07de51d787f0699d9345"
|
| 41 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 42 |
}
|
| 43 |
}
|
|
|
|
| 4 |
"source": "Frozen implementation used for the October 2026 technical report",
|
| 5 |
"packaging_changes": [
|
| 6 |
"Package-relative imports.",
|
| 7 |
+
"Convolution and recurrence retain independent cache dtypes.",
|
| 8 |
+
"CUDA runtime defaults to BF16 recurrent storage at every batch size; FP32 update accumulation is unchanged.",
|
| 9 |
+
"Physical-ring decode attention uses grouped zero-stride KV views with PyTorch EFFICIENT_ATTENTION to avoid observed cuDNN forward nondeterminism without duplicating persistent KV."
|
| 10 |
],
|
| 11 |
"components": {
|
| 12 |
"b1_bf16_selected.py": {
|
| 13 |
"report_source_sha256": "82d7484627684ed3c2375a8d0339497399e67cf24ae705cddb45215cfe75f57d",
|
| 14 |
+
"release_sha256": "7c96b9fa282c87f094b0dfe174d6618a25d9df2c71bcae38812e4d36c711becd"
|
| 15 |
},
|
| 16 |
"b1_bf16_fusions.py": {
|
| 17 |
"report_source_sha256": "9cd816ae32ee03e312445291dd859ff41b43acee94ee916de1e213db98d11a9b",
|
|
|
|
| 41 |
"report_source_sha256": "02677ef9d025423264c6b4a9bfaf85c82d5675aa74bf07de51d787f0699d9345",
|
| 42 |
"release_sha256": "02677ef9d025423264c6b4a9bfaf85c82d5675aa74bf07de51d787f0699d9345"
|
| 43 |
}
|
| 44 |
+
},
|
| 45 |
+
"bf16_state_reference_run": "edgerock-128k-bestbatch-20261018-edge-bf16state-v3",
|
| 46 |
+
"physical_ring_attention_change": {
|
| 47 |
+
"source_diagnostic_run": "edgerock-bf16-runtime-grouped-sdpa-repeat-20261018-v16",
|
| 48 |
+
"release_inference_kernels_sha256": "564820a8692d5e9526040463b746e3cbc8b709c41b2e84f7188cdae60b067292",
|
| 49 |
+
"formal_acceptance": {
|
| 50 |
+
"status": "passed",
|
| 51 |
+
"date": "2026-10-18",
|
| 52 |
+
"run_id": "edgerock-bf16-runtime-acceptance-20261018-v17",
|
| 53 |
+
"slurm_job_id": 422927,
|
| 54 |
+
"environment": "H800; PyTorch 2.11.0+cu130; cuDNN 91900",
|
| 55 |
+
"reference": "Frozen source with external grouped EFFICIENT_ATTENTION correction; released candidate ran unwrapped. Equivalence is under this common corrected backend, not against historical nondeterministic cuDNN outputs.",
|
| 56 |
+
"checks": [
|
| 57 |
+
"two independent reference/release process pairs per batch",
|
| 58 |
+
"token equality across implementations and within repeats",
|
| 59 |
+
"BF16 prefill and decode recurrent storage",
|
| 60 |
+
"independent per-request prefill",
|
| 61 |
+
"cache byte equality",
|
| 62 |
+
"original peak-memory tolerance",
|
| 63 |
+
"unwrapped release source"
|
| 64 |
+
],
|
| 65 |
+
"speed_protocol": {
|
| 66 |
+
"input_tokens": 4096,
|
| 67 |
+
"output_tokens": 2048,
|
| 68 |
+
"full_generation_warmup_calls": 1,
|
| 69 |
+
"timed_calls": 3,
|
| 70 |
+
"metric": "output tokens / generation wall time including prefill",
|
| 71 |
+
"baseline": "original frozen default cuDNN path",
|
| 72 |
+
"release": "in-source grouped EFFICIENT_ATTENTION",
|
| 73 |
+
"paper_result": false
|
| 74 |
+
},
|
| 75 |
+
"batches": {
|
| 76 |
+
"1": {
|
| 77 |
+
"manifest_sha256": "79b7a52fec334a62854e0ce6ccd4f9d623042736087be49e8fa2c742c4fb24c5",
|
| 78 |
+
"validation_passed": true,
|
| 79 |
+
"output_token_sha256": "851192f484b0dc2ba83232a381055637958c3fa4b69377320cc162b951321935",
|
| 80 |
+
"baseline_trials_output_tps": [
|
| 81 |
+
230.4101261568867,
|
| 82 |
+
230.38532371553555,
|
| 83 |
+
219.52501767745193
|
| 84 |
+
],
|
| 85 |
+
"release_trials_output_tps": [
|
| 86 |
+
210.74617372026032,
|
| 87 |
+
210.7263298727412,
|
| 88 |
+
203.97152321588845
|
| 89 |
+
],
|
| 90 |
+
"baseline_median_output_tps": 230.38532371553555,
|
| 91 |
+
"release_median_output_tps": 210.7263298727412,
|
| 92 |
+
"release_over_baseline": 0.9146690703828514,
|
| 93 |
+
"baseline_peak_allocated_gib": 14.269504070281982,
|
| 94 |
+
"release_peak_allocated_gib": 14.269504070281982,
|
| 95 |
+
"release_timed_tokens_repeatable": true,
|
| 96 |
+
"cache_bytes_equal": true
|
| 97 |
+
},
|
| 98 |
+
"512": {
|
| 99 |
+
"manifest_sha256": "920d43855924e25521d1259908637528511e5a974bcd3382a777894f4d12e938",
|
| 100 |
+
"validation_passed": true,
|
| 101 |
+
"output_token_sha256": "ad1dd751ef4b468ea0f1183b2228655f173ca91fedcf45c6457305f597d71454",
|
| 102 |
+
"baseline_trials_output_tps": [
|
| 103 |
+
8270.370076665207,
|
| 104 |
+
8272.754923447415,
|
| 105 |
+
8233.773287549524
|
| 106 |
+
],
|
| 107 |
+
"release_trials_output_tps": [
|
| 108 |
+
8218.093798671816,
|
| 109 |
+
8217.189832268046,
|
| 110 |
+
8168.14852213838
|
| 111 |
+
],
|
| 112 |
+
"baseline_median_output_tps": 8270.370076665207,
|
| 113 |
+
"release_median_output_tps": 8217.189832268046,
|
| 114 |
+
"release_over_baseline": 0.9935697866112172,
|
| 115 |
+
"baseline_peak_allocated_gib": 63.54788160324097,
|
| 116 |
+
"release_peak_allocated_gib": 63.54788160324097,
|
| 117 |
+
"release_timed_tokens_repeatable": true,
|
| 118 |
+
"cache_bytes_equal": true
|
| 119 |
+
}
|
| 120 |
+
}
|
| 121 |
+
}
|
| 122 |
}
|
| 123 |
}
|
runtime/optimizations/b1_bf16_selected.py
CHANGED
|
@@ -2,8 +2,8 @@ import torch
|
|
| 2 |
|
| 3 |
|
| 4 |
def install(model):
|
| 5 |
-
"""Install the selected BF16 fusion stack before prefill
|
| 6 |
-
assert model.config.gdn_recurrent_state_storage == '
|
| 7 |
assert all(p.is_cuda and p.dtype == torch.bfloat16 for p in model.parameters())
|
| 8 |
from . import b1_bf16_fusions
|
| 9 |
b1_bf16_fusions.install(model)
|
|
|
|
| 2 |
|
| 3 |
|
| 4 |
def install(model):
|
| 5 |
+
"""Install the selected BF16 fusion stack before prefill with BF16 weights, KV and recurrent storage."""
|
| 6 |
+
assert model.config.gdn_recurrent_state_storage == 'bf16_non_anchor'
|
| 7 |
assert all(p.is_cuda and p.dtype == torch.bfloat16 for p in model.parameters())
|
| 8 |
from . import b1_bf16_fusions
|
| 9 |
b1_bf16_fusions.install(model)
|