Skip to documentation
SLOP

tiny.accy.artifact.fingerprint

Reference tiny.accy artifact fingerprint

Defined in artifact.

API (3)

Actions

Public operations.

No direct callersNo direct callsartifactfingerprint
Static calls · unresolved targets: unknown · external targets: unknown.

Source

Called byCallstest sourcelib.accy.src.artifact.fingerprinttest: artifact plan fingerprint inclu...test sourcelib.accy.src.artifact.fingerprinttest: artifact plan fingerprint inclu...private sourcelib.accy.src.artifact.fingerprinthashBackendTargetProfileprivate sourcelib.accy.src.artifact.fingerprinthashPlannedKernelprivate sourcelib.accy.src.artifact.fingerprinthashPlannedSlotprivate sourcelib.accy.src.artifact.fingerprinthashU64artifact.fingerprintartifactPlan
Static calls · unresolved targets: 0 · external targets: 2.
Called byCallstest sourcelib.accy.src.artifact.fingerprinttest: kernel call registry fingerprin...private sourcelib.accy.src.artifact.fingerprinthashKernelCallArtifactprivate sourcelib.accy.src.artifact.fingerprinthashU64artifact.fingerprintkernelCallRegistry
Static calls · unresolved targets: 0 · external targets: 2.
Called byCallsNo direct callersprivate sourcelib.accy.src.artifact.fingerprinthashLaunchResourcePlanartifact.fingerprintlaunchResourcePlan
Static calls · unresolved targets: 0 · external targets: 2.

Source: lib/accy/src/artifact/fingerprint.zig

zig
const std = @import("std");const gpu = @import("gpu");const choir_abi = @import("choir_abi");const choir = @import("choir");const model = @import("model/root.zig");const plan_mod = @import("plan.zig");const preparation = @import("../preparation/root.zig");pub fn artifactPlan(value: *const plan_mod.BackendArtifactPlan) u64 {    var hasher = choir.product.incremental.FingerprintBuilder{};    hasher.updateBytes("accy.artifact.plan");    hashBackendTargetProfile(&hasher, value.target_profile);    hashU64(&hasher, @backingInt(value.backend_kind));    hashU64(&hasher, @backingInt(value.format));    hashU64(&hasher, value.slots.len);    for (value.slots) |slot| hashPlannedSlot(&hasher, slot);    hashU64(&hasher, value.input_slot_ids.len);    for (value.input_slot_ids) |slot_id| hashU64(&hasher, slot_id);    hashU64(&hasher, value.output_slot_ids.len);    for (value.output_slot_ids) |slot_id| hashU64(&hasher, slot_id);    hashU64(&hasher, value.kernels.items.len);    for (value.kernels.items) |kernel| hashPlannedKernel(&hasher, kernel);    hashU64(&hasher, value.total_kernel_ops);    hashU64(&hasher, value.total_static_bytes);    return hasher.finish();}pub fn kernelCallRegistry(value: ?*const model.KernelCallRegistry) u64 {    var hasher = choir.product.incremental.FingerprintBuilder{};    hasher.updateBytes("accy.artifact.kernel_call_registry");    hashU64(&hasher, @intFromBool(value != null));    const registry = value orelse return hasher.finish();    hashU64(&hasher, registry.entries.len);    for (registry.entries) |entry| hashKernelCallArtifact(&hasher, entry);    return hasher.finish();}pub fn launchResourcePlan(value: plan_mod.LaunchResourcePlan) u64 {    var hasher = choir.product.incremental.FingerprintBuilder{};    hasher.updateBytes("accy.artifact.launch_resource_plan");    hashLaunchResourcePlan(&hasher, value);    return hasher.finish();}fn hashBackendTargetProfile(hasher: *choir.product.incremental.FingerprintBuilder, profile: anytype) void {    hashU64(hasher, @backingInt(profile.backend_kind));    hashU64(hasher, @backingInt(profile.artifact_format));    hashU64(hasher, @backingInt(profile.math_tier));    hashU64(hasher, profile.dtype_bits);    hashU64(hasher, profile.feature_bits);}fn hashPlannedSlot(hasher: *choir.product.incremental.FingerprintBuilder, slot: plan_mod.PlannedSlot) void {    hashU64(hasher, slot.slot_id);    hashBufferRole(hasher, slot.role);    hashU64(hasher, @backingInt(slot.dtype));    hashU64(hasher, @backingInt(slot.memory_space));    hashU64(hasher, @backingInt(slot.memory_access));    hashU64(hasher, @backingInt(slot.boundary_transfer));    hashU64(hasher, @backingInt(slot.layout_kind));    hashU64(hasher, slot.dims.len);    for (slot.dims) |dim| hashU64(hasher, @bitCast(dim));    hashOptionalU64Slice(hasher, slot.element_strides);    hashU64(hasher, slot.minor_to_major.len);    for (slot.minor_to_major) |minor| hashU64(hasher, minor);    hashOptionalU64(hasher, slot.element_count);    hashOptionalU64(hasher, slot.byte_size);    hashU64(hasher, slot.alignment);    hashU64(hasher, @intFromBool(slot.contiguous));    hashU64(hasher, @intFromBool(slot.static_layout));    hashU64(hasher, slot.layout_fingerprint);    hashBytes(hasher, slot.constant_payload);}fn hashBufferRole(hasher: *choir.product.incremental.FingerprintBuilder, role: anytype) void {    hashU64(hasher, @intFromBool(role.input));    hashU64(hasher, @intFromBool(role.output));    hashU64(hasher, @intFromBool(role.temporary));    hashU64(hasher, @intFromBool(role.constant));}fn hashPlannedKernel(hasher: *choir.product.incremental.FingerprintBuilder, kernel: plan_mod.PlannedKernel) void {    hashPlannedKernelCompile(hasher, kernel.compile);    hashU64(hasher, kernel.kernel_id);    hashU64(hasher, kernel.work_item_id);    hashU64(hasher, kernel.output_slot_id);    hashU64(hasher, kernel.input_slot_ids.len);    for (kernel.input_slot_ids) |slot_id| hashU64(hasher, slot_id);    hashU64(hasher, kernel.output_layout_fingerprint);    hashU64(hasher, kernel.input_layout_fingerprint);    hashU64(hasher, kernel.element_count);    hashU64(hasher, kernel.op_count);    hashScheduleResourceEstimate(hasher, kernel.resources);    hashKernelArtifact(hasher, kernel.artifact);    hashLaunchResourcePlan(hasher, kernel.launch_resources);    hashOptionalKernelCallLaunch(hasher, kernel.kernel_call_launch);    hashU64(hasher, @backingInt(kernel.element_count_argument));    hashU64(hasher, kernel.element_count_argument_value);    hashU64(hasher, kernel.runtime_scalar_argument_count);    hashU64(hasher, kernel.runtime_scalar_defaults.len);    for (kernel.runtime_scalar_defaults) |argument| hashKernelScalarArgument(hasher, argument);    hashU64(hasher, kernel.static_arguments.len);    for (kernel.static_arguments) |argument| hashKernelScalarArgument(hasher, argument);}fn hashPlannedKernelCompile(hasher: *choir.product.incremental.FingerprintBuilder, compile: plan_mod.PlannedKernelCompileContract) void {    hashU64(hasher, @backingInt(compile.source));    hashU64(hasher, @backingInt(compile.launch));    hashU64(hasher, @backingInt(compile.format));    hashBytes(hasher, compile.entry_name);    hashU64(hasher, compile.argument_count);    hashU64(hasher, compile.required_dtypes.bits);    hashAcceleratorFeatures(hasher, compile.required_features);    hashSubgroupRequirements(hasher, compile.required_subgroup);    hashOptionalU64(hasher, compile.shape_family_fingerprint);    hashU64(hasher, @backingInt(compile.payload));    hashU64(hasher, compile.payload_byte_count);}fn hashAcceleratorFeatures(hasher: *choir.product.incremental.FingerprintBuilder, features: choir_abi.Features) void {    hashU64(hasher, @intFromBool(features.atomic_i32));    hashU64(hasher, @intFromBool(features.atomic_u32));    hashU64(hasher, @intFromBool(features.atomic_index));    hashU64(hasher, @intFromBool(features.atomic_f32_add_device));    hashU64(hasher, @intFromBool(features.atomic_f32_add_shared));    hashU64(hasher, @intFromBool(features.unsupported_atomic));    hashU64(hasher, @intFromBool(features.async_copy));    hashU64(hasher, @intFromBool(features.tensor_cores));    hashU64(hasher, @intFromBool(features.cooperative_matrix));    hashU64(hasher, @intFromBool(features.dynamic_shared_memory));    hashU64(hasher, @intFromBool(features.indirect_launch));}fn hashSubgroupRequirements(hasher: *choir.product.incremental.FingerprintBuilder, requirements: choir_abi.SubgroupRequirements) void {    hashU64(hasher, @intFromBool(requirements.supported));    hashU64(hasher, requirements.size_min);    hashU64(hasher, requirements.size_max);    hashU64(hasher, @intFromBool(requirements.shuffle));    hashU64(hasher, @intFromBool(requirements.ballot));    hashU64(hasher, @intFromBool(requirements.vote));    hashU64(hasher, @intFromBool(requirements.arithmetic));    hashU64(hasher, @intFromBool(requirements.scan));}fn hashScheduleResourceEstimate(hasher: *choir.product.incremental.FingerprintBuilder, resources: anytype) void {    hashU64(hasher, resources.element_count);    hashU64(hasher, resources.element_size);    hashU64(hasher, resources.op_count);    hashU64(hasher, resources.external_input_value_count);    hashU64(hasher, resources.external_operand_count);    hashU64(hasher, resources.chain_operand_count);    hashU64(hasher, resources.estimated_element_ops);    hashU64(hasher, resources.static_read_bytes);    hashU64(hasher, resources.static_write_bytes);    hashU64(hasher, resources.static_total_bytes);    hashU64(hasher, @intFromBool(resources.static_bytes_complete));}fn hashKernelArtifact(hasher: *choir.product.incremental.FingerprintBuilder, artifact: gpu.KernelArtifact) void {    hashU64(hasher, @backingInt(artifact.backend));    hashU64(hasher, @backingInt(artifact.format));    hashBytes(hasher, artifact.entry_name);    hashU64(hasher, artifact.argument_count);    hashOptionalBytes(hasher, artifact.diagnostic_id);    hashArtifactPayload(hasher, artifact.payload);    hashU64(hasher, @backingInt(artifact.payload_ownership));}fn hashArtifactPayload(hasher: *choir.product.incremental.FingerprintBuilder, payload: gpu.ArtifactPayload) void {    hashU64(hasher, @backingInt(payload));    switch (payload) {        .none => {},        .bytes => |bytes| hashBytes(hasher, bytes),        .text => |text| hashBytes(hasher, text),        .words_u32 => |words| {            hashU64(hasher, words.len);            for (words) |word| hashU64(hasher, word);        },        .external => |external| {            hashU64(hasher, @intFromPtr(external.ptr));            hashU64(hasher, @intFromBool(external.deinit_fn != null));        },    }}fn hashCompilePayload(hasher: *choir.product.incremental.FingerprintBuilder, payload: gpu.CompilePayload) void {    hashU64(hasher, @backingInt(payload));    switch (payload) {        .none => {},        .bytes => |bytes| hashBytes(hasher, bytes),        .text => |text| hashBytes(hasher, text),        .words_u32 => |words| {            hashU64(hasher, words.len);            for (words) |word| hashU64(hasher, word);        },    }}fn hashKernelCallArtifact(hasher: *choir.product.incremental.FingerprintBuilder, artifact: model.KernelCallArtifact) void {    hashBytes(hasher, artifact.target);    hashU64(hasher, artifact.version);    hashU64(hasher, @backingInt(artifact.format));    hashBytes(hasher, artifact.entry_name);    hashU64(hasher, artifact.argument_count);    hashOptionalU64(hasher, artifact.shape_family_fingerprint);    hashOptionalKernelCallShapeProfile(hasher, artifact.shape_profile);    hashU64(hasher, artifact.required_dtypes.bits);    hashAcceleratorFeatures(hasher, artifact.required_features);    hashSubgroupRequirements(hasher, artifact.required_subgroup);    hashCompilePayload(hasher, artifact.payload);    hashKernelCallLaunch(hasher, artifact.launch);    hashU64(hasher, @backingInt(artifact.element_count_argument));    hashU64(hasher, artifact.runtime_scalar_argument_count);    hashU64(hasher, artifact.static_arguments.len);    for (artifact.static_arguments) |argument| hashKernelScalarArgument(hasher, argument);}fn hashOptionalKernelCallShapeProfile(hasher: *choir.product.incremental.FingerprintBuilder, profile: ?model.KernelCallShapeProfile) void {    hashU64(hasher, @intFromBool(profile != null));    if (profile) |value| {        hashBytes(hasher, value.name);        hashU64(hasher, value.fingerprint);        hashU64(hasher, value.dimensions.len);        for (value.dimensions) |dimension| {            hashBytes(hasher, dimension.name);            hashU64(hasher, dimension.runtime_scalar_argument_index);            hashShapeBounds(hasher, dimension.bounds);        }    }}fn hashShapeBounds(hasher: *choir.product.incremental.FingerprintBuilder, bounds: anytype) void {    hashOptionalU64(hasher, bounds.min);    hashOptionalU64(hasher, bounds.opt);    hashOptionalU64(hasher, bounds.max);}fn hashOptionalKernelCallLaunch(hasher: *choir.product.incremental.FingerprintBuilder, launch: ?model.KernelCallLaunch) void {    hashU64(hasher, @intFromBool(launch != null));    if (launch) |value| hashKernelCallLaunch(hasher, value);}fn hashKernelCallLaunch(hasher: *choir.product.incremental.FingerprintBuilder, launch: model.KernelCallLaunch) void {    hashU64(hasher, @backingInt(launch));    switch (launch) {        .derived => |derived| hashKernelCallDerivedLaunch(hasher, derived),        .fixed => |geometry| hashLaunchGeometry(hasher, geometry),    }}fn hashKernelCallDerivedLaunch(hasher: *choir.product.incremental.FingerprintBuilder, launch: model.KernelCallDerivedLaunch) void {    for (launch.grid) |axis| hashKernelCallDerivedLaunchAxis(hasher, axis);    for (launch.threadgroup) |extent| hashU64(hasher, extent);    hashU64(hasher, launch.dynamic_shared_memory_bytes);}fn hashKernelCallDerivedLaunchAxis(hasher: *choir.product.incremental.FingerprintBuilder, axis: model.KernelCallDerivedLaunchAxis) void {    hashU64(hasher, @backingInt(axis));    switch (axis) {        .fixed => |extent| hashU64(hasher, extent),        .runtime_u32_ceil_div => |runtime| {            hashU64(hasher, runtime.argument_index);            hashU64(hasher, runtime.divisor);        },    }}fn hashLaunchResourcePlan(hasher: *choir.product.incremental.FingerprintBuilder, plan: plan_mod.LaunchResourcePlan) void {    hashU64(hasher, @backingInt(plan.format));    hashU64(hasher, plan.element_count);    hashLaunchGeometry(hasher, plan.geometry);    hashOptionalU32(hasher, plan.subgroup_size);    hashU64(hasher, @intFromBool(plan.subgroup_aligned));    hashU64(hasher, @intFromBool(plan.fixed_threadgroup));    hashU64(hasher, @backingInt(plan.resource_class));    hashU64(hasher, plan.element_ops_per_kib);    hashU64(hasher, plan.estimated_static_bytes_per_threadgroup);    hashU64(hasher, plan.estimated_element_ops_per_threadgroup);    hashU64(hasher, @intFromBool(plan.static_bytes_complete));    hashLaunchTilePlan(hasher, plan.tile);    hashU64(hasher, plan.candidate_count);    for (plan.candidates[0..plan.candidate_count]) |candidate| hashLaunchResourceCandidate(hasher, candidate);}fn hashLaunchResourceCandidate(hasher: *choir.product.incremental.FingerprintBuilder, candidate: plan_mod.LaunchResourceCandidate) void {    hashLaunchGeometry(hasher, candidate.geometry);    hashU64(hasher, candidate.score);    hashU64(hasher, candidate.estimated_static_bytes_per_threadgroup);    hashU64(hasher, candidate.estimated_element_ops_per_threadgroup);    hashLaunchTilePlan(hasher, candidate.tile);}fn hashLaunchGeometry(hasher: *choir.product.incremental.FingerprintBuilder, geometry: choir_abi.LaunchGeometry) void {    for (geometry.grid) |value| hashU64(hasher, value);    for (geometry.threadgroup) |value| hashU64(hasher, value);    hashU64(hasher, geometry.dynamic_shared_memory_bytes);}fn hashLaunchTilePlan(hasher: *choir.product.incremental.FingerprintBuilder, tile: plan_mod.LaunchTilePlan) void {    hashU64(hasher, @backingInt(tile.kind));    hashU64(hasher, tile.m);    hashU64(hasher, tile.n);    hashU64(hasher, tile.k);    hashU64(hasher, tile.batch);    hashOptionalDType(hasher, tile.input_dtype);    hashOptionalDType(hasher, tile.output_dtype);    hashU64(hasher, tile.input_tile_bytes);    hashU64(hasher, tile.output_tile_bytes);    hashU64(hasher, tile.scratch_memory_bytes);    hashU64(hasher, @backingInt(tile.reduction_kind));    hashU64(hasher, tile.reduction_rank);    hashU64(hasher, tile.reduction_axis);    hashU64(hasher, tile.reduction_extent);}fn hashKernelScalarArgument(hasher: *choir.product.incremental.FingerprintBuilder, argument: choir_abi.ScalarArgument) void {    hashU64(hasher, @backingInt(argument));    switch (argument) {        .i32 => |value| hashU64(hasher, @as(u32, @bitCast(value))),        .u32 => |value| hashU64(hasher, value),        .i64 => |value| hashU64(hasher, @bitCast(value)),        .u64 => |value| hashU64(hasher, value),        .f32 => |value| hashU64(hasher, @as(u32, @bitCast(value))),        .f64 => |value| hashU64(hasher, @bitCast(value)),    }}fn hashOptionalDType(hasher: *choir.product.incremental.FingerprintBuilder, dtype: ?choir_abi.DType) void {    hasher.updateBool(dtype != null);    if (dtype) |value| hashU64(hasher, @backingInt(value));}fn hashOptionalU32(hasher: *choir.product.incremental.FingerprintBuilder, value: ?u32) void {    hasher.updateBool(value != null);    if (value) |payload| hasher.updateU32(payload);}fn hashOptionalU64(hasher: *choir.product.incremental.FingerprintBuilder, value: ?u64) void {    hasher.updateOptionalU64(value);}fn hashOptionalU64Slice(hasher: *choir.product.incremental.FingerprintBuilder, value: ?[]const u64) void {    hasher.updateOptionalU64Slice(value);}fn hashOptionalBytes(hasher: *choir.product.incremental.FingerprintBuilder, value: ?[]const u8) void {    hasher.updateBool(value != null);    if (value) |bytes| hashBytes(hasher, bytes);}fn hashBytes(hasher: *choir.product.incremental.FingerprintBuilder, bytes: []const u8) void {    hasher.updateBytes(bytes);}fn hashU64(hasher: *choir.product.incremental.FingerprintBuilder, value: u64) void {    hasher.updateU64(value);}test "artifact plan fingerprint includes backend target profile" {    const allocator = std.testing.allocator;    var f32_plan = plan_mod.BackendArtifactPlan.init(allocator, .{        .backend_kind = .cuda,        .artifact_format = .cuda_ptx,        .dtype_bits = gpu.DTypeSet.init(&.{.f32}).bits,    });    defer f32_plan.deinit();    var f16_f32_plan = plan_mod.BackendArtifactPlan.init(allocator, .{        .backend_kind = .cuda,        .artifact_format = .cuda_ptx,        .dtype_bits = gpu.DTypeSet.init(&.{ .f16, .f32 }).bits,    });    defer f16_f32_plan.deinit();    const tf32_profile = try preparation.BackendTargetProfile.initWithMathTier(.{        .identity = .{            .backend = .cuda,            .family = .nvidia_cuda,        },        .dtypes = gpu.DTypeSet.init(&.{.f32}),        .features = .{ .tensor_cores = true },        .artifact_formats = gpu.ArtifactFormatSet.init(&.{.cuda_ptx}),    }, .cuda, .cuda_ptx, .tf32_tensor);    var tf32_plan = plan_mod.BackendArtifactPlan.init(allocator, tf32_profile);    defer tf32_plan.deinit();    try std.testing.expect(artifactPlan(&f32_plan) != artifactPlan(&f16_f32_plan));    try std.testing.expect(artifactPlan(&f32_plan) != artifactPlan(&tf32_plan));}test "artifact plan fingerprint includes shape family compile identity" {    const allocator = std.testing.allocator;    var first = try standalonePlanWithShapeFamilyFingerprint(allocator, 0x1111);    defer first.deinit();    var same = try standalonePlanWithShapeFamilyFingerprint(allocator, 0x1111);    defer same.deinit();    var changed = try standalonePlanWithShapeFamilyFingerprint(allocator, 0x2222);    defer changed.deinit();    try std.testing.expectEqual(artifactPlan(&first), artifactPlan(&same));    try std.testing.expect(artifactPlan(&first) != artifactPlan(&changed));}fn standalonePlanWithShapeFamilyFingerprint(allocator: std.mem.Allocator, family_fingerprint: u64) !plan_mod.BackendArtifactPlan {    var plan = plan_mod.BackendArtifactPlan.init(allocator, .{        .backend_kind = .cuda,        .artifact_format = .cuda_ptx,        .dtype_bits = gpu.DTypeSet.init(&.{.f32}).bits,    });    errdefer plan.deinit();    var artifact = try gpu.KernelArtifact.init(allocator, .{        .backend = .cuda,        .format = .cuda_ptx,        .entry_name = "kernel_call",        .argument_count = 3,    });    var artifact_owned = true;    errdefer if (artifact_owned) artifact.deinit();    try artifact.setOwnedText("// ptx");    var compile = try plan_mod.PlannedKernelCompileContract.init(        allocator,        .kernel_call,        .kernel_call,        .cuda_ptx,        "kernel_call",        3,        gpu.DTypeSet.init(&.{.f32}),        .{},        .{},        family_fingerprint,        .{ .text = "// ptx" },    );    var compile_owned = true;    errdefer if (compile_owned) compile.deinit(allocator);    try plan.addStandaloneKernel(        artifact,        .{            .format = .cuda_ptx,            .element_count = 1,            .geometry = .{                .grid = .{ 1, 1, 1 },                .threadgroup = .{ 1, 1, 1 },            },        },        compile,        .{},    );    artifact_owned = false;    compile_owned = false;    return plan;}test "kernel call registry fingerprint includes payload and launch contract" {    const ptx = ".visible .entry first() { ret; }";    const other_ptx = ".visible .entry second() { ret; }";    const first_entries = [_]model.KernelCallArtifact{.{        .target = "accy.custom.scale",        .version = 1,        .format = .cuda_ptx,        .entry_name = "first",        .argument_count = 5,        .required_dtypes = gpu.DTypeSet.init(&.{.f32}),        .payload = .{ .text = ptx },        .launch = .{ .fixed = .{            .grid = .{ 1, 1, 1 },            .threadgroup = .{ 8, 1, 1 },            .dynamic_shared_memory_bytes = 0,        } },        .element_count_argument = .scalar_u32,        .shape_family_fingerprint = 0xaaaa,        .static_arguments = &.{.{ .u32 = 7 }},    }};    const first = model.KernelCallRegistry{ .entries = &first_entries };    const first_again = model.KernelCallRegistry{ .entries = &first_entries };    const changed_payload_entries = [_]model.KernelCallArtifact{.{        .target = "accy.custom.scale",        .version = 1,        .format = .cuda_ptx,        .entry_name = "first",        .argument_count = 5,        .required_dtypes = gpu.DTypeSet.init(&.{.f32}),        .payload = .{ .text = other_ptx },        .launch = .{ .fixed = .{            .grid = .{ 1, 1, 1 },            .threadgroup = .{ 8, 1, 1 },            .dynamic_shared_memory_bytes = 0,        } },        .element_count_argument = .scalar_u32,        .shape_family_fingerprint = 0xaaaa,        .static_arguments = &.{.{ .u32 = 7 }},    }};    const changed_payload = model.KernelCallRegistry{ .entries = &changed_payload_entries };    const changed_launch_entries = [_]model.KernelCallArtifact{.{        .target = "accy.custom.scale",        .version = 1,        .format = .cuda_ptx,        .entry_name = "first",        .argument_count = 5,        .required_dtypes = gpu.DTypeSet.init(&.{.f32}),        .payload = .{ .text = ptx },        .launch = .{ .fixed = .{            .grid = .{ 2, 1, 1 },            .threadgroup = .{ 8, 1, 1 },            .dynamic_shared_memory_bytes = 0,        } },        .element_count_argument = .scalar_u32,        .shape_family_fingerprint = 0xaaaa,        .static_arguments = &.{.{ .u32 = 7 }},    }};    const changed_launch = model.KernelCallRegistry{ .entries = &changed_launch_entries };    const changed_shape_family_entries = [_]model.KernelCallArtifact{.{        .target = "accy.custom.scale",        .version = 1,        .format = .cuda_ptx,        .entry_name = "first",        .argument_count = 5,        .required_dtypes = gpu.DTypeSet.init(&.{.f32}),        .payload = .{ .text = ptx },        .launch = .{ .fixed = .{            .grid = .{ 1, 1, 1 },            .threadgroup = .{ 8, 1, 1 },            .dynamic_shared_memory_bytes = 0,        } },        .element_count_argument = .scalar_u32,        .shape_family_fingerprint = 0xbbbb,        .static_arguments = &.{.{ .u32 = 7 }},    }};    const changed_shape_family = model.KernelCallRegistry{ .entries = &changed_shape_family_entries };    try std.testing.expectEqual(kernelCallRegistry(&first), kernelCallRegistry(&first_again));    try std.testing.expect(kernelCallRegistry(&first) != kernelCallRegistry(null));    try std.testing.expect(kernelCallRegistry(&first) != kernelCallRegistry(&changed_payload));    try std.testing.expect(kernelCallRegistry(&first) != kernelCallRegistry(&changed_launch));    try std.testing.expect(kernelCallRegistry(&first) != kernelCallRegistry(&changed_shape_family));}

Source: lib/accy/src/artifact/root.zig:1

zig
pub const fingerprint = @import("fingerprint.zig");

Audit

Definitions4
Public names7
Members0
Version26.7.0
Revisiondaab053ee433