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

- Tests: four host steps that no CI job runs build and pass again: `test-gemma4-affine-host` pins `affine_mm.metal`'s current bytes, the compile-only Metal contract runners import `masked_sources`, `compile-metal-residency-host` imports `kimi_k3`, and the GLM Metal fact tests give `facts()` a host device object instead of an undefined one, which crashed them at random (#2409, part of #2031).

- Flash Next on CUDA with `TF_FLASHNEXT_KV_PAGES`: a shared round's grouped draft head reads and writes each stream's own pages, so paged streams' replies equal their runs alone again, and paged decode runs as fast as unpaged; default settings are unchanged (#2244). Thanks to @Arminova.

- Tests: `zig build test-glm-snapshots-host` builds again: its copies module imports `core`, which `cuda_snaps.zig` reads for `TF_GLM_PROMPT_TAIL` since #2226 (#2403). Thanks to @Bizuayeu.
Expand Down
1 change: 1 addition & 0 deletions zig/build/fsr.zig
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ pub fn deviceSteps(b: *std.Build, metal: *std.Build.Module, engine: *std.Build.M
b.step("test-fsr-metal", "GPU: uncached four-slot synthetic MoE equals resident at every node and logit").dependOn(&run.step);
b.step("compile-fsr-metal-gate-host", "Compile the real FSR device gate without shader compilation or execution").dependOn(&device_test.step);
const contract = b.createModule(.{ .root_source_file = b.path("zig/tests/contract/metal_main.zig"), .target = b.graph.host, .link_libc = true, .imports = &.{ .{ .name = "metal", .module = metal }, .{ .name = "tensorfold", .module = engine }, .{ .name = "kernel_sources", .module = sources }, .{ .name = "contract", .module = @import("kernel_contract.zig").module(b, b.graph.host, .debug) }, .{ .name = "h3_kernels", .module = b.createModule(.{ .root_source_file = b.path("zig/kernels/metal/h3/kernels.zig") }) }, .{ .name = "ling_metal", .module = b.createModule(.{ .root_source_file = b.path("zig/kernels/metal/ling/sources.zig") }) }, .{ .name = "ling_route", .module = b.createModule(.{ .root_source_file = b.path("zig/src/families/ling/route.zig") }) } } });
contract.addImport("masked_sources", b.createModule(.{ .root_source_file = b.path("zig/masked_value_sources.zig"), .imports = &.{.{ .name = "kernel_sources", .module = sources }} }));
const compile_contract = b.addObject(.{ .name = "fsr-metal-contract", .root_module = b.createModule(.{ .root_source_file = b.path("zig/fsr_contract_compile.zig"), .target = b.graph.host, .link_libc = true, .imports = &.{.{ .name = "contract_main", .module = contract }} }) });
_ = compile_contract.getEmittedBin();
b.step("compile-fsr-metal-contract-host", "Compile the actual Metal contract entry with inert embedded bytes and no execution").dependOn(&compile_contract.step);
Expand Down
1 change: 1 addition & 0 deletions zig/build/gemma4_host.zig
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ pub fn compileHost(b: *std.Build, metal: *std.Build.Module, engine: *std.Build.M
runner.addImport("h3_kernels", b.createModule(.{ .root_source_file = b.path("zig/kernels/metal/h3/kernels.zig") }));
runner.addAnonymousImport("ling_metal", .{ .root_source_file = b.path("zig/kernels/metal/ling/sources.zig") });
runner.addAnonymousImport("ling_route", .{ .root_source_file = b.path("zig/src/families/ling/route.zig") });
runner.addImport("masked_sources", b.createModule(.{ .root_source_file = b.path("zig/masked_value_sources.zig"), .imports = &.{.{ .name = "kernel_sources", .module = sources }} }));
const contract_root = b.createModule(.{ .root_source_file = b.path("zig/gemma4_contract_compile.zig"), .target = b.graph.host, .link_libc = true, .imports = &.{.{ .name = "runner", .module = runner }} });
const contract_object = b.addObject(.{ .name = "gemma4-contract-compile", .root_module = contract_root });
_ = contract_object.getEmittedBin();
Expand Down
6 changes: 4 additions & 2 deletions zig/build/residency_host.zig
Original file line number Diff line number Diff line change
Expand Up @@ -23,18 +23,20 @@ pub fn steps(b: *std.Build) void {
pub fn compileHost(b: *std.Build, metal: *std.Build.Module, engine: *std.Build.Module, lanes: *std.Build.Module) void {
const api = b.createModule(.{ .root_source_file = b.path("zig/src/core/engine_api.zig"), .target = b.graph.host, .link_libc = true, .imports = &.{.{ .name = "lanes", .module = lanes }} });
const host = b.createModule(.{ .root_source_file = b.path("zig/src/native/metal.zig"), .target = b.graph.host, .link_libc = true, .imports = &.{ .{ .name = "metal", .module = metal }, .{ .name = "tensorfold", .module = engine }, .{ .name = "engine_api", .module = api } } });
const bytes = b.addWriteFiles().add("residency-drama-empty.zig", "pub const bytes: []const u8 = &.{};\n");
const bytes = b.createModule(.{ .root_source_file = b.addWriteFiles().add("residency-drama-empty.zig", "pub const bytes: []const u8 = &.{};\n") });
const tokenizer = b.createModule(.{ .root_source_file = b.path("zig/src/core/tokenizer/tokenizer.zig"), .target = b.graph.host, .link_libc = true });
const rounds = b.createModule(.{ .root_source_file = b.path("zig/src/core/frame_rounds.zig"), .target = b.graph.host });
const shim = b.addWriteFiles().add("residency-drama-core.zig", "pub const safetensors = @import(\"tensorfold\").safetensors;\npub const tokenizer = @import(\"tokenizer\");\npub const frame_rounds = @import(\"frame_rounds\");\n");
const core = b.createModule(.{ .root_source_file = shim, .target = b.graph.host, .imports = &.{ .{ .name = "tensorfold", .module = engine }, .{ .name = "tokenizer", .module = tokenizer }, .{ .name = "frame_rounds", .module = rounds } } });
const drama = b.createModule(.{ .root_source_file = b.path("zig/src/families/drama3/drama3_metal.zig"), .target = b.graph.host, .link_libc = true, .imports = &.{ .{ .name = "metal", .module = metal }, .{ .name = "core", .module = core }, .{ .name = "drama3_metallib", .module = b.createModule(.{ .root_source_file = bytes }) } } });
const drama = b.createModule(.{ .root_source_file = b.path("zig/src/families/drama3/drama3_metal.zig"), .target = b.graph.host, .link_libc = true, .imports = &.{ .{ .name = "metal", .module = metal }, .{ .name = "core", .module = core }, .{ .name = "drama3_metallib", .module = bytes } } });
host.addImport("core", core);
host.addImport("tokenizer", tokenizer);
host.addImport("drama3", drama);
// native/metal_slide.zig imports living: the engine module's own (a file belongs to one module)
host.addImport("living", engine.import_table.get("living") orelse @panic("the engine has no living import"));
@import("qwen4.zig").metalNative(b, b.graph.host, host);
host.addImport("kimi_k3", @import("metal_targets.zig").kimiModule(b, b.graph.host, .Debug, metal, engine, lanes));
host.addImport("kimi_metallib", bytes);
b.step("test-metal-formats-host", "Actual Metal format offers with inert images and no device").dependOn(&b.addRunArtifact(b.addTest(.{ .root_module = host, .filters = &.{"Metal capabilities:"} })).step);
const root = b.createModule(.{ .root_source_file = b.path("zig/residency_native_compile.zig"), .target = b.graph.host, .link_libc = true, .imports = &.{.{ .name = "host", .module = host }} });
const object = b.addObject(.{ .name = "metal-residency-native", .root_module = root });
Expand Down
2 changes: 1 addition & 1 deletion zig/gemma4_shared_affine_test.zig
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ test "landed Metal source bytes are pinned without shader compilation" {
{
var hash: [32]u8 = undefined;
std.crypto.hash.sha2.Sha256.hash(ks.core_affine_mm, &hash, .{});
try std.testing.expectEqualStrings("d8f47cbbddf24502ca2c16cfdef0672731cc2dbe59ad027f47a3e662bcf8f627", &std.fmt.bytesToHex(hash, .lower));
try std.testing.expectEqualStrings("a91a353981c4e24142673ab9c97e9a449b973751bd5df7ad7c980757046cf61e", &std.fmt.bytesToHex(hash, .lower));
}
{
var hash: [32]u8 = undefined;
Expand Down
8 changes: 8 additions & 0 deletions zig/src/families/glm/backend.zig
Original file line number Diff line number Diff line change
Expand Up @@ -441,6 +441,10 @@ test "zero grant: GLM Metal MTP resumes after a long priced skip" {
var e: Engine = undefined;
e.w = &w;
e.ep = null;
const objc = @import("metal").objc;
const no_arch = objc.msg(objc.Id, objc.class("NSObject"), "new", .{}); // facts() asks it for tensor units, no GPU
defer objc.release(no_arch);
e.device = .{ .id = no_arch };
var slots: [16]slots_mod.Slot = undefined;
var sl: slots_mod.Slots = undefined;
sl.e = &e;
Expand All @@ -457,6 +461,10 @@ test "shared head costs: GLM Metal MTP retains costed copy grants" {
var e: Engine = undefined;
e.w = &w;
e.ep = null;
const objc = @import("metal").objc;
const no_arch = objc.msg(objc.Id, objc.class("NSObject"), "new", .{}); // facts() asks it for tensor units, no GPU
defer objc.release(no_arch);
e.device = .{ .id = no_arch };
var slots: [16]slots_mod.Slot = undefined;
var sl: slots_mod.Slots = undefined;
sl.e = &e;
Expand Down
Loading