Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ Each release's page on GitHub has its notes and measurements. See [the 1.0.0 rel

## Unreleased

- GLM-5.3-Flash on CUDA: `TF_GLM_KV_SHARE=n` with `TF_KV_PAGES=on` keeps prompts as the KV pool's pages in the shared prompt store (the one `TF_QWEN_KV_SHARE` uses), with at most n states past them, on one GPU and at tensor parallel. Where main's flat store has no room for a long state (GB10s at TP=3 with the 1M window), a 64k message sent again resumes in about 1.7 s instead of prefilling for 36 s; token-id prompts resume at every width (#1510). Unset, nothing changes.

- MOSS-Image-Base's transformer runs on CUDA too, through the same test tool (`tf-moss-image`) and cases as on Metal (#1528, for #1518). It runs on an RTX 5090 (sm_120) and a GB10 (sm_121) and refuses other GPUs; the prompt encoder and image decoder stay in torch, and nothing is served yet. Against the publisher's torch bf16 pipeline, every step's cosine is 0.99967 or better, the same step run twice gives the same bytes, and a 1024x1024 picture is 44.0 dB (RTX 5090) and 45.9 dB (GB10) PSNR from torch's. Its 50 guided steps at 1024x1024 take 24.6 s on an RTX 5090 and 69.6 s on a GB10, 1.26x and 2.03x faster than torch. Its four kernels and full attention at head dim 128, a new instance of the vision towers' kernel, pass the kernel contract with five planted controls red; the towers' existing attention kernels compile to the same SASS. See [the recipe](docs/recipes/moss-image-cuda.md). Thanks to @BobClawblaw.

- DeepSeek-V4.x replies carry the Spark recipe's per-response stats (`prompt`, `cached`, `ttft_s`, `finish`, `completion`, `prefill_s`, `decode_s`, `rounds`, `drafted`, `accepted`) in their `tensorfold` block, after its own keys; `TENSORFOLD_WIRE=spark` turns them on for any family and `native` turns them off.
Expand Down
5 changes: 3 additions & 2 deletions zig/build/cuda.zig
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,8 @@ pub fn targets(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.bu
runner.addImport("exlr8_frozen", b.createModule(.{ .root_source_file = b.path("zig/tests/fixtures/exlr8/frozen.zig"), .target = target, .optimize = optimize }));
runner.addImport("exlr8_frozen_dense", b.createModule(.{ .root_source_file = b.path("zig/tests/fixtures/exlr8/frozen_dense.zig"), .target = target, .optimize = optimize }));
for (exlr8_build.denseModules(b, target, optimize, exlr8, exlr8_tests[0])) |m| runner.addImport(m.name, m.module);
runner.addImport("glm_cuda", glmCuda(b, target, optimize, cuda, mods.core, mods.lanes, mods.heat));
const glm_cuda = glmCuda(b, target, optimize, cuda, mods.core, mods.lanes, mods.heat, mods.api);
runner.addImport("glm_cuda", glm_cuda);
@import("minimax_cuda.zig").targets(b, target, optimize, strip, cuda, mods.core, mods.lanes, runner);
for ([_]struct { []const u8, *std.Build.Module }{ .{ "kolibri1", kolibri1Module(b, target, optimize, cuda, mods.core, mods.lanes) }, .{ "dory", @import("dory.zig").module(b, target, optimize, cuda, mods.core, mods.lanes) } }) |m| runner.addImport(m[0], m[1]);
runner.addImport("gemma4_cuda", @import("gemma4_cuda.zig").module(b, target, optimize, cuda, mods.core, mods.lanes));
Expand Down Expand Up @@ -449,7 +450,7 @@ pub fn hostTests(b: *std.Build, draft_ids: *std.Build.Module, build_options: *st
// the contract's attention reference (tests/cuda/contract_attn.zig): its allocations under failure
const attn_ref = b.createModule(.{ .root_source_file = b.path("zig/tests/cuda/contract_attn.zig"), .target = host, .optimize = .debug, .imports = &.{.{ .name = "core", .module = mods.core }} });
step.dependOn(&b.addRunArtifact(b.addTest(.{ .root_module = attn_ref })).step);
const glm = glmCuda(b, host, .debug, cuda, mods.core, mods.lanes, mods.heat);
const glm = glmCuda(b, host, .debug, cuda, mods.core, mods.lanes, mods.heat, mods.api);
@import("glm_family_host.zig").steps(b, cuda, glm, mods, step);
@import("kolibri.zig").host(b, kolibri1Module(b, host, .debug, cuda, mods.core, mods.lanes), native_modules.api, step);
@import("gemma4_cuda.zig").host(b, @import("gemma4_cuda.zig").module(b, host, .debug, cuda, mods.core, mods.lanes), step);
Expand Down
7 changes: 4 additions & 3 deletions zig/build/cuda_engines.zig
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
//! The CUDA engines a native server opens (native/cuda.zig) and the family modules they import.
const std = @import("std");

/// The GLM-5.3-Flash CUDA family over the runtime, the core, the lane core, canon's shares and core/heat.zig.
pub fn glmCuda(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.builtin.OptimizeMode, cuda: *std.Build.Module, core: *std.Build.Module, lanes: *std.Build.Module, heat: *std.Build.Module) *std.Build.Module {
/// The GLM-5.3-Flash CUDA family over the runtime, the core, the lane core, canon's shares, core/heat.zig, engine_api.
pub fn glmCuda(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.builtin.OptimizeMode, cuda: *std.Build.Module, core: *std.Build.Module, lanes: *std.Build.Module, heat: *std.Build.Module, api: *std.Build.Module) *std.Build.Module {
const canon = b.createModule(.{ .root_source_file = b.path("zig/src/cluster/canon.zig"), .target = target, .optimize = optimize });
const m = b.createModule(.{ .root_source_file = b.path("zig/src/families/glm/cuda.zig"), .target = target, .optimize = optimize, .link_libc = true });
m.addImport("cuda", cuda);
Expand All @@ -11,6 +11,7 @@ pub fn glmCuda(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.bu
m.addImport("lanes", lanes);
m.addImport("heat", heat);
m.addImport("tp", @import("tp.zig").module(b, target, optimize, cuda)); // over the engine's own cuda module
m.addImport("engine_api", api); // TF_GLM_KV_SHARE's prompt_radix store: family()'s, the server's
return m;
}

Expand Down Expand Up @@ -48,7 +49,7 @@ pub fn engines(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.bu
.{ .name = "lfm2", .module = lfm2Module(b, target, optimize, cuda, core) },
.{ .name = "core", .module = core },
.{ .name = "flashnext", .module = flashnextModule(b, target, optimize, cuda, core, lanes, qwen_vision, api) },
.{ .name = "glm_cuda", .module = glmCuda(b, target, optimize, cuda, core, lanes, heat) },
.{ .name = "glm_cuda", .module = glmCuda(b, target, optimize, cuda, core, lanes, heat, api) },
.{ .name = "minimax_m3_cuda", .module = @import("minimax_cuda.zig").module(b, target, optimize, cuda, core, lanes) },
.{ .name = "qwen35", .module = qwen35 },
.{ .name = "kolibri1", .module = @import("kolibri.zig").module(b, target, optimize, cuda, core, lanes) },
Expand Down
8 changes: 4 additions & 4 deletions zig/build/glm_family_host.zig
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ pub fn steps(b: *std.Build, cuda: *std.Build.Module, glm: *std.Build.Module, mod
const page_contract_run = b.addRunArtifact(b.addTest(.{ .root_module = page_contract, .filters = &.{"GLM page contract:"} }));
b.step("test-glm-page-contract-host", "GLM paged contract case and planted-control inventory without devices").dependOn(&page_contract_run.step);
step.dependOn(&page_contract_run.step);
const api = b.createModule(.{ .root_source_file = b.path("zig/src/core/engine_api.zig"), .target = host, .optimize = .debug, .link_libc = true, .imports = &.{.{ .name = "lanes", .module = mods.lanes }} });
const api = glm.import_table.get("engine_api").?; // the family's own (TF_GLM_KV_SHARE's store): one module, one set of types
const admission = b.createModule(.{ .root_source_file = b.path("zig/glm_admission_host.zig"), .target = host, .optimize = .debug, .link_libc = true, .imports = &.{ .{ .name = "glm", .module = glm }, .{ .name = "lanes", .module = mods.lanes }, .{ .name = "engine_api", .module = api } } });
const admission_run = b.addRunArtifact(b.addTest(.{ .root_module = admission, .filters = &.{"GLM CUDA admission:"} }));
b.step("test-glm-admission-host", "Real GLM admission capabilities through the lane worker without GPU work").dependOn(&admission_run.step);
Expand All @@ -59,14 +59,14 @@ pub fn steps(b: *std.Build, cuda: *std.Build.Module, glm: *std.Build.Module, mod
}

pub fn compile(b: *std.Build, target: std.Build.ResolvedTarget, cuda: *std.Build.Module, mods: anytype, comptime makeGlm: anytype) void {
const fp8_gate = b.createModule(.{ .root_source_file = b.path("zig/tests/cuda/glm_ref_fp8.zig"), .target = target, .optimize = .debug, .link_libc = true, .imports = &.{ .{ .name = "glm_cuda", .module = makeGlm(b, target, .debug, cuda, mods.core, mods.lanes, mods.heat) }, .{ .name = "cuda", .module = cuda }, .{ .name = "core", .module = mods.core } } });
const fp8_gate = b.createModule(.{ .root_source_file = b.path("zig/tests/cuda/glm_ref_fp8.zig"), .target = target, .optimize = .debug, .link_libc = true, .imports = &.{ .{ .name = "glm_cuda", .module = makeGlm(b, target, .debug, cuda, mods.core, mods.lanes, mods.heat, mods.api) }, .{ .name = "cuda", .module = cuda }, .{ .name = "core", .module = mods.core } } });
const fp8_object = b.addObject(.{ .name = "glm-fp8-gate-compile", .root_module = b.createModule(.{ .root_source_file = b.path("zig/glm_fp8_gate_compile.zig"), .target = target, .optimize = .debug, .link_libc = true, .imports = &.{.{ .name = "gate", .module = fp8_gate }} }) });
_ = fp8_object.getEmittedBin();
b.step("compile-glm-fp8-gate-host", "Compile synthetic FP8 write/read and FP64 device checks with inert images, never execute").dependOn(&fp8_object.step);
const glm_open = b.addObject(.{ .name = "glm-open-check", .root_module = b.createModule(.{ .root_source_file = b.path("zig/glm_open_compile.zig"), .target = target, .optimize = .debug, .link_libc = true, .imports = &.{.{ .name = "glm", .module = makeGlm(b, target, .debug, cuda, mods.core, mods.lanes, mods.heat) }} }) });
const glm_open = b.addObject(.{ .name = "glm-open-check", .root_module = b.createModule(.{ .root_source_file = b.path("zig/glm_open_compile.zig"), .target = target, .optimize = .debug, .link_libc = true, .imports = &.{.{ .name = "glm", .module = makeGlm(b, target, .debug, cuda, mods.core, mods.lanes, mods.heat, mods.api) }} }) });
_ = glm_open.getEmittedBin();
b.step("compile-glm-native-open", "Compile the actual GLM Linux open body with empty GPU images").dependOn(&glm_open.step);
const prompt_gate = b.createModule(.{ .root_source_file = b.path("zig/tests/cuda/glm_mm_fixed_tests.zig"), .target = target, .optimize = .debug, .link_libc = true, .imports = &.{ .{ .name = "glm_cuda", .module = makeGlm(b, target, .debug, cuda, mods.core, mods.lanes, mods.heat) }, .{ .name = "cuda", .module = cuda } } });
const prompt_gate = b.createModule(.{ .root_source_file = b.path("zig/tests/cuda/glm_mm_fixed_tests.zig"), .target = target, .optimize = .debug, .link_libc = true, .imports = &.{ .{ .name = "glm_cuda", .module = makeGlm(b, target, .debug, cuda, mods.core, mods.lanes, mods.heat, mods.api) }, .{ .name = "cuda", .module = cuda } } });
const prompt_gate_compile = b.addObject(.{ .name = "glm-prompt-gate-compile", .root_module = b.createModule(.{ .root_source_file = b.path("zig/glm_prompt_gate_compile.zig"), .target = target, .optimize = .debug, .link_libc = true, .imports = &.{.{ .name = "gate", .module = prompt_gate }} }) });
_ = prompt_gate_compile.getEmittedBin();
b.step("compile-glm-prompt-gate-host", "Compile the actual device prompt comparison gate with inert images").dependOn(&prompt_gate_compile.step);
Expand Down
12 changes: 6 additions & 6 deletions zig/glm_pages_host.zig
Original file line number Diff line number Diff line change
Expand Up @@ -205,15 +205,15 @@ test "GLM pages: a follower refuses a duplicate owner and rolls back a failed ta
defer f.deinit();
f.p.leader = false;
F.fail_put = true;
try t.expectError(error.NotReady, f.p.map(0, &.{ 3, 2 }));
try t.expectError(error.NotReady, f.p.map(0, &.{ 3, 2 }, 0));
try t.expectEqual(@as(usize, 0), f.p.leases[0].ids.items.len);
try t.expect(!f.p.used[0]);
F.fail_put = false;
try f.p.map(0, &.{ 3, 2 });
try t.expectError(error.BadStep, f.p.map(0, &.{ 1, 0 }));
try f.p.map(0, &.{ 3, 2 }, 0);
try t.expectError(error.BadStep, f.p.map(0, &.{ 1, 0 }, 0));
try t.expectEqualSlices(u32, &.{ 3, 2 }, f.e.seqs.items[0].?.st.pages);
f.p.close(0);
try f.p.map(0, &.{ 1, 0 });
try f.p.map(0, &.{ 1, 0 }, 0);
f.p.close(0);
try t.expect(f.p.pool.idle());
}
Expand Down Expand Up @@ -264,13 +264,13 @@ test "GLM pages: a failed seat binding returns its pages and lane before retry"
defer back.deinit();
var stream = try lanes.Stream.init(t.allocator, .{ .id = "page-test", .prompt = &.{100}, .max_new = 8 });
defer stream.deinit(t.allocator);
try t.expectError(error.OutOfMemory, back.seat(&stream, 1, 8));
try t.expectError(error.OutOfMemory, back.seat(&stream, 1, 8, &.{}));
try t.expectEqual(@as(usize, 0), back.lanes.count());
try t.expect(f.p.pool.idle());
try t.expectEqual(@as(usize, 8), f.p.pool.census().free);
try t.expectEqual(@as(u32, 1), f.e.slot);
v.gpa = t.allocator;
try t.expectEqual(@as(usize, 1), (try back.seat(&stream, 1, 8)).len);
try t.expectEqual(@as(usize, 1), (try back.seat(&stream, 1, 8, &.{})).len);
try t.expectEqual(@as(usize, 1), back.lanes.count());
try t.expectEqual(@as(u32, 0), f.e.slot);
f.e.release(0);
Expand Down
2 changes: 2 additions & 0 deletions zig/src/families/glm/cuda.zig
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ test {
_ = @import("cuda_pages_test.zig");
_ = @import("cuda_ranks_test.zig");
_ = @import("cuda_roce_multi.zig");
_ = @import("cuda_lanes_test.zig");
_ = experts;
_ = exl3;
_ = vision;
Expand Down Expand Up @@ -78,6 +79,7 @@ test {
_ = lanes;
_ = native;
_ = @import("cuda_qpack.zig");
_ = @import("cuda_prefix.zig");
_ = @import("cuda_mtp_chance.zig");
_ = @import("cuda_tile.zig");
_ = @import("heat"); // upstream's heat bands, run where the GLM ranks use them
Expand Down
1 change: 1 addition & 0 deletions zig/src/families/glm/cuda_engine.zig
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ pub const Engine = struct {
pages: ?*pages_mod.Pages = null, // the other streams' KV pages and sequences (cuda_pages), once the server attached them
index_split: bool = false, // the next prompt step's indexer rows split across the ranks: rank 0's choice, the chunk's flag 2
index_splits: u64 = 0, // prompt steps whose indexer rows split (glm-split-check counts them)
share_pages: bool = false, // TF_GLM_KV_SHARE: a kept state leaves its prefix's pages to the prompt cache that holds them

/// Opens rank `rank` of `world` over `comm`; the ranks agree on settings (cuda_ranks) before the weights load.
pub fn init(gpa: std.mem.Allocator, io: std.Io, d: *const cuda.Driver, ctx: *const cuda.Context, checkpoint: []const u8, lib: *const cuda.nccl.Library, comm: cuda.nccl.Comm, rank: usize, world: usize, o: Options) !*Engine {
Expand Down
2 changes: 1 addition & 1 deletion zig/src/families/glm/cuda_engine_types.zig
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ pub const Seq = struct {
};

/// One rank's copy of a kept prompt state: the state arena's bytes and the host fields beside them.
pub const Snap = struct { lease: @import("cuda_snapshot_pages.zig").Lease, len: usize, pos: usize, mtp_len: usize, cur: []u1, bases: [2]usize };
pub const Snap = struct { lease: @import("cuda_snapshot_pages.zig").Lease, len: usize, pos: usize, mtp_len: usize, cur: []u1, bases: [2]usize, shared: usize = 0 };

/// Where a prompt pass resumes: a kept state (every rank holds `id`) at `at`, a multiple of the chunk rows.
pub const Resume = struct { id: u64, at: usize };
Expand Down
23 changes: 13 additions & 10 deletions zig/src/families/glm/cuda_follow.zig
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ pub const Header = extern struct {
kind: u32,
n: u32 = 0, // ids that follow
depth: u32 = 0, // draft: drafts to chain; chunk: where it starts; shared: its parts
flags: u32 = 0, // begin: sampled; draft: from the prompt (1), chances (2); prefill, chunk: prompt_logprobs (1); chunk: indexer rows split (2); verify, shared: whole rows
a: u64 = 0, // keep: rows; prefill, chunk: the kept state it resumes (0: none); redraw: the prompt's length
flags: u32 = 0, // begin: sampled; draft: from the prompt (1), chances (2); prefill, chunk: prompt_logprobs (1); chunk: indexer rows split (2); verify, shared: whole rows; snapshots: pages shared
a: u64 = 0, // begin: the prompt cache's pages first in its table; keep: rows; prefill, chunk: the kept state it resumes (0: none); redraw: the prompt's length
seed: u64 = 0, // begin: the sampling seed; prefill, chunk: the kept state's position
temperature: f64 = 0,
top_p: f64 = 0,
Expand Down Expand Up @@ -172,14 +172,14 @@ pub const Leader = struct {
}

pub fn begin(x: Leader, s: ?sampler.Sampling) !void {
return x.beginOn(s, &.{});
return x.beginOn(s, &.{}, 0);
}

/// `begin` on a paged sequence: the page ids it maps (rank 0's lease) go with the step, to every rank's table.
pub fn beginOn(x: Leader, s: ?sampler.Sampling, pages: []const u32) !void {
/// `begin` on a paged sequence: its page ids (rank 0's lease, the cache's `kept` first) go to every rank's table.
pub fn beginOn(x: Leader, s: ?sampler.Sampling, pages: []const u32, kept: usize) !void {
try x.flush();
const c = sampler.check(s);
var h: Header = .{ .kind = @backingInt(Kind.begin) };
var h: Header = .{ .kind = @backingInt(Kind.begin), .a = kept };
if (c) |v| {
h.flags = 1;
h.seed = v.seed;
Expand All @@ -192,9 +192,9 @@ pub const Leader = struct {
try x.e.begin(c);
}

/// Every rank's prompt cache at rank 0's budget (snapshots.agree): the others make theirs on this step.
/// Every rank's prompt cache at rank 0's budget (snapshots.agree), its states past the pool's pages as rank 0's.
pub fn snapshots(x: Leader, budget: u64) !void {
try x.send(.{ .kind = @backingInt(Kind.snapshots), .a = budget }, &.{});
try x.send(.{ .kind = @backingInt(Kind.snapshots), .a = budget, .flags = @intFromBool(x.e.share_pages) }, &.{});
try @import("cuda_snapshots.zig").agree(x.e, budget);
}

Expand Down Expand Up @@ -331,7 +331,7 @@ pub fn follow(e: *Engine, link: *Link) !void {
e.structured = structuredStep(h); // rank 0 alone masks them
switch (kind) {
.begin => {
if (step.ids.len > 0) try (e.pages orelse return error.BadStep).map(h.slot, step.ids);
if (step.ids.len > 0) try (e.pages orelse return error.BadStep).map(h.slot, step.ids, std.math.cast(usize, h.a) orelse return error.BadStep);
try e.beginFollowing(if (h.flags & 1 != 0) .{ .seed = h.seed, .temperature = h.temperature, .top_p = h.top_p, .min_p = h.min_p, .top_k = h.top_k } else null);
},
.pool => {
Expand Down Expand Up @@ -399,7 +399,10 @@ pub fn follow(e: *Engine, link: *Link) !void {
try v.take(h.slot, step.ids);
try link.rows(v.rows.ptr, v.rowCount() * vcfg.out_hidden * 2);
},
.snapshots => try @import("cuda_snapshots.zig").agree(e, h.a),
.snapshots => {
e.share_pages = h.flags & 1 != 0; // TF_GLM_KV_SHARE on rank 0: a kept state leaves the prompt cache's pages out
try @import("cuda_snapshots.zig").agree(e, h.a);
},
.drop => for (step.ids) |id| e.dropState(id),
.release => e.release(h.slot),
.idle => cuda.tp_watch.sleep(e.io),
Expand Down
Loading
Loading