Download offload/dspark/native/tests/test_fidelity_gpu.py from ProprietaryLegal/dsv41-offload: direct link, hf CLI and curl.
- Browser
- Download file 6.1 kB
-
https://huggingface.co/ProprietaryLegal/dsv41-offload/resolve/main/offload/dspark/native/tests/test_fidelity_gpu.py
- Command line
-
hf download hf://ProprietaryLegal/dsv41-offload/offload/dspark/native/tests/test_fidelity_gpu.py
-
curl -L -o test_fidelity_gpu.py https://huggingface.co/ProprietaryLegal/dsv41-offload/resolve/main/offload/dspark/native/tests/test_fidelity_gpu.py
6.1 kB
| """Run under the N4 UUID/flock wrapper; fixtures are synthetic, never captured.""" | |
| from __future__ import annotations | |
| import math | |
| import pytest | |
| import torch | |
| from offload.dspark.native.attention import attention_into | |
| from offload.dspark.native.fidelity_reference import markov_logits, online_attention | |
| from offload.dspark.native.ops import markov_logits_fp32 | |
| pytestmark = pytest.mark.skipif(not torch.cuda.is_available(), reason="requires authorized N4 GPU hold") | |
| def test_online64_ring_and_graph(last: int) -> None: | |
| g = torch.Generator().manual_seed(38) | |
| b, k, h, d = 2, 5, 32, 512 | |
| # BF16 x BF16 integer dots are exact, isolating online softmax scheduling. | |
| q = torch.randint(-2, 3, (b, k, h, d), generator=g).bfloat16() | |
| ring = torch.randint(-2, 3, (4, 3, 128, d), generator=g).bfloat16()[:, 1] | |
| block = torch.randint(-2, 3, (b, k, d), generator=g).bfloat16() | |
| positions = torch.full((4, 128), -1, dtype=torch.int64) | |
| lo = max(0, last - 127) | |
| pp = torch.arange(lo, last + 1) | |
| for slot in (1, 3): | |
| positions[slot, pp % 128] = pp | |
| slots = torch.tensor([3, 1]) | |
| lows = torch.full((b,), lo) | |
| highs = torch.full((b,), last) | |
| sink = torch.linspace(-2., 4., h) | |
| nc = min(128, last + 1) | |
| kv = torch.cat((ring[slots], block), 1) | |
| idx = torch.cat((torch.arange(nc), 128 + torch.arange(k))).view(1, 1, -1).expand(b, k, -1) | |
| want = online_attention(q, kv, sink, idx, d ** -.5, fp64=True) | |
| args = (q.cuda(), ring.cuda(), positions.cuda(), slots.cuda(), lows.cuda(), highs.cuda(), block.cuda(), sink.cuda()) | |
| out = torch.empty_like(args[0]) | |
| ptr = out.data_ptr() | |
| attention_into(*args, d ** -.5, out) | |
| got = out.cpu() | |
| # FP32 exp/reduction differences only; no weight or QDQ error is involved. | |
| assert (got.float() - want.float()).norm() / want.float().norm() < .003 | |
| torch.testing.assert_close(got, want, rtol=.008, atol=.004) | |
| stream = torch.cuda.Stream() # type: ignore[no-untyped-call] | |
| stream.wait_stream(torch.cuda.current_stream()) | |
| with torch.cuda.stream(stream): | |
| attention_into(*args, d ** -.5, out) | |
| stream.synchronize() | |
| graph = torch.cuda.CUDAGraph() | |
| with torch.cuda.graph(graph, stream=stream): | |
| attention_into(*args, d ** -.5, out) | |
| graph.replay() | |
| torch.cuda.synchronize() | |
| assert out.data_ptr() == ptr | |
| assert torch.equal(out.cpu(), got) | |
| def test_fp32_markov_exact_dyadic_and_near_tie() -> None: | |
| g = torch.Generator().manual_seed(42) | |
| embed = torch.randint(-2, 3, (32, 256), generator=g).bfloat16() | |
| weight = torch.randint(-2, 3, (513, 256), generator=g).bfloat16() | |
| base = torch.randn(3, 513, generator=g) | |
| prev = torch.tensor([0, 15, 31]) | |
| want = markov_logits(base, prev, embed, weight, fp64=True) | |
| got = markov_logits_fp32(base.cuda(), prev.cuda(), embed.cuda(), weight.cuda()) | |
| assert torch.equal(got.cpu(), want) | |
| def test_online64_exact_constant_values() -> None: | |
| q = torch.zeros(1, 5, 32, 512, dtype=torch.bfloat16, device="cuda") | |
| ring = torch.ones(1, 128, 512, dtype=torch.bfloat16, device="cuda") | |
| positions = torch.arange(128, device="cuda").view(1, -1) | |
| slot = torch.zeros(1, dtype=torch.int64, device="cuda") | |
| last = torch.full_like(slot, 127) | |
| block = torch.ones(1, 5, 512, dtype=torch.bfloat16, device="cuda") | |
| sink = torch.zeros(32, device="cuda") | |
| out = torch.empty_like(q) | |
| attention_into(q, ring, positions, slot, slot, last, block, sink, 512 ** -.5, out) | |
| assert torch.equal(out, torch.full_like(q, 133 / 134)) | |
| def test_mixed_short_and_wrapped_windows() -> None: | |
| g = torch.Generator().manual_seed(91) | |
| q = torch.randint(-2, 3, (2, 5, 32, 512), generator=g).bfloat16() | |
| ring = torch.randint(-2, 3, (4, 128, 512), generator=g).bfloat16() | |
| block = torch.randint(-2, 3, (2, 5, 512), generator=g).bfloat16() | |
| sink = torch.linspace(-2., 4., 32) | |
| positions = torch.full((4, 128), -1, dtype=torch.int64) | |
| slots, last = torch.tensor([3, 0]), torch.tensor([62, 900000]) | |
| lo = (last - 127).clamp_min(0) | |
| expected = [] | |
| for b in range(2): | |
| p = torch.arange(int(lo[b]), int(last[b]) + 1) | |
| positions[slots[b], p % 128] = p | |
| kv = torch.cat((ring[slots[b]], block[b]), 0).unsqueeze(0) | |
| idx = torch.cat((torch.arange(min(128, int(last[b]) + 1)), 128 + torch.arange(5))) | |
| expected.append(online_attention(q[b:b+1], kv, sink, idx.view(1, 1, -1).expand(1, 5, -1), | |
| 512 ** -.5, fp64=True)) | |
| args = (q.cuda(), ring.cuda(), positions.cuda(), slots.cuda(), lo.cuda(), last.cuda(), block.cuda(), sink.cuda()) | |
| out = torch.empty_like(args[0]) | |
| attention_into(*args, 512 ** -.5, out) | |
| want = torch.cat(expected) | |
| got = out.cpu() | |
| assert (got.float() - want.float()).norm() / want.float().norm() < .003 | |
| torch.testing.assert_close(got, want, rtol=.008, atol=.004) | |
| def test_online_blocks_and_sink_rounding_are_required() -> None: | |
| # First block:64 keys at score0/value1. Next block:5 keys at log(3)/value0. | |
| # Sink weight9 is added last. Official output=64/(64+15+9)=8/11. | |
| # Rounding P around the global/sink maximum instead produces a different | |
| # BF16 value (~.73047 versus .72656), so a single-pass implementation fails. | |
| q = torch.zeros(1, 5, 32, 512, dtype=torch.bfloat16, device="cuda") | |
| q[..., 0] = 1 | |
| ring = torch.zeros(1, 128, 512, dtype=torch.bfloat16, device="cuda") | |
| ring[:, :64, 1] = 1 | |
| positions = torch.full((1, 128), -1, dtype=torch.int64, device="cuda") | |
| positions[:, :64] = torch.arange(64, device="cuda") | |
| slot = torch.zeros(1, dtype=torch.int64, device="cuda") | |
| last = torch.full_like(slot, 63) | |
| block = torch.zeros(1, 5, 512, dtype=torch.bfloat16, device="cuda") | |
| block[..., 0] = 1 | |
| sink = torch.full((32,), 2 * math.log(3), device="cuda") | |
| out = torch.empty_like(q) | |
| attention_into(q, ring, positions, slot, slot, last, block, sink, math.log(3), out) | |
| assert torch.equal(out[..., 1], torch.full_like(out[..., 1], 8 / 11)) | |