tiny.accy.preparation.kernelization.product
Defined in preparation.kernelization.
API (64)
Actions
Public operations.
GeneratedKernelSummaries.deinitGeneratedKernelSummaries.lenGeneratedKernelSummaries.summaryGeneratedKernelSummaries.summaryForWorkKernelOutline.inputCountKernelOutlinePlanAnalysis.deinitKernelOutlinePlanAnalysis.getKernelForWorkKernelOutlinePlanAnalysis.initKernelOutlinePlanAnalysis.kernelCountKernelizationAnalysis.baseStorageBound: The kernel stage calls this for its work bound to charge the result object before any kernel is generated, so compilation can refuse a pass that would exceed the caller's limits.KernelizationAnalysis.copyKernelSummariesKernelizationAnalysis.deinitKernelizationAnalysis.getForWorkKernelizationAnalysis.initKernelizationAnalysis.kernelCountKernelizationAnalysis.kernelProgramKernelizationAnalysis.kernelProgramForWorkKernelizationAnalysis.kernelSummaryKernelizationAnalysis.kernelSummaryForWorkKernelizationAnalysis.reserveKernelCapacityLoweredKernel.deinitLoweredKernel.launchGeometryLoweredKernel.requiredDTypesLoweredKernel.runtimeScalarArgumentCountLoweredKernel.summaryaddKerneldotGeneralBlockTileFordotGeneralMmaTileFordynamicSharedMemoryBytesreductionAtomicPlanForreductionSingleBlockThreadsreductionWarpRowsThreads
Types and contracts
Public types and contracts.
DotGeneralBlockTileDotGeneralDescriptionDotGeneralMmaTileDotGeneralStaticDimsElementwiseKernelElementwiseRank2PlanElementwiseVectorPlanFlashAttentionPlanGeneratedKernelProgramGeneratedKernelSummariesGeneratedKernelSummaryGeneratedScheduleGeneratedScheduleKindKernelOutlineKernelOutlineKindKernelOutlinePlanAnalysisKernelizationAnalysisLoweredKernelLoweredKernelBodyReductionAtomicPlanReductionDescriptionReductionInitReductionInitValueReductionKindReductionStaticDimsReductionWarpRowsPlanRowPipelinePlanScanPlanShapeKernel
Values and defaults
Public values and defaults.
Source
Source: lib/accy/src/preparation/kernelization/model/outline.zig:11
pub const KernelOutline = struct { id: usize, name: []u8, kind: KernelOutlineKind, work_item_id: usize, root: *ir.Operation, input_slot_ids: []usize, output_slot_id: usize, element_count: u64, op_count: usize, pub fn inputCount(self: KernelOutline) usize { return self.input_slot_ids.len; } fn deinit(self: *KernelOutline, allocator: std.mem.Allocator) void { allocator.free(self.name); allocator.free(self.input_slot_ids); self.* = undefined; }};Source: lib/accy/src/preparation/kernelization/model/outline.zig:33
pub const KernelOutlinePlanAnalysis = struct { allocator: std.mem.Allocator, kernels: std.ArrayListUnmanaged(KernelOutline), work_to_kernel: std.AutoHashMap(usize, usize), total_input_slots: usize = 0, total_scheduled_ops: usize = 0, pub fn init(allocator: std.mem.Allocator) KernelOutlinePlanAnalysis { return .{ .allocator = allocator, .kernels = .empty, .work_to_kernel = std.AutoHashMap(usize, usize).init(allocator), }; } pub fn deinit(self: *KernelOutlinePlanAnalysis) void { for (self.kernels.items) |*kernel| { kernel.deinit(self.allocator); } self.kernels.deinit(self.allocator); self.work_to_kernel.deinit(); self.* = undefined; } pub fn kernelCount(self: KernelOutlinePlanAnalysis) usize { return self.kernels.items.len; } pub fn getKernelForWork( self: *const KernelOutlinePlanAnalysis, work_item_id: usize, ) ?*const KernelOutline { const index = self.work_to_kernel.get(work_item_id) orelse return null; return &self.kernels.items[index]; }};Source: lib/accy/src/preparation/kernelization/model/product.zig:320
pub const DotGeneralDescription = struct { input_dtype: choir_abi.DType, output_dtype: choir_abi.DType, dims: DotGeneralStaticDims,};Source: lib/accy/src/preparation/kernelization/model/product.zig:14
pub const ElementwiseKernel = enum { add, sub, mul, div, min, max, neg, abs, sqrt, exp, log, tanh, sin, cos, tan, floor, round, trunc, pow, atan2, convert, compare, select,};Source: lib/accy/src/preparation/kernelization/model/product.zig:68
pub const GeneratedKernelSummaries = struct { allocator: std.mem.Allocator, items: []GeneratedKernelSummary, pub fn deinit(self: *GeneratedKernelSummaries) void { for (self.items) |item| { self.allocator.free(item.entry_name); } self.allocator.free(self.items); self.* = undefined; } pub fn len(self: *const GeneratedKernelSummaries) usize { return self.items.len; } pub fn summary( self: *const GeneratedKernelSummaries, kernel_index: usize, ) !GeneratedKernelSummary { if (kernel_index >= self.items.len) return error.InvalidIndex; return self.items[kernel_index]; } pub fn summaryForWork( self: *const GeneratedKernelSummaries, work_item_id: usize, ) !GeneratedKernelSummary { for (self.items) |item| { if (item.work_item_id == work_item_id) return item; } return error.MissingKernelization; }};Source: lib/accy/src/preparation/kernelization/model/product.zig:58
pub const GeneratedKernelSummary = struct { work_item_id: usize, entry_name: []const u8, argument_count: u32, body_fingerprint: u64, dynamic_shared_memory_bytes: u32 = 0, schedule: GeneratedSchedule, launch_geometry: ?choir_abi.LaunchGeometry,};Source: lib/accy/src/preparation/kernelization/model/product.zig:180
pub const KernelizationAnalysis = struct { allocator: std.mem.Allocator, context: *ir.Context, kernels: std.ArrayListUnmanaged(LoweredKernel), work_to_kernel: std.AutoHashMap(usize, usize), /// The kernel stage calls this for its work bound to charge the result object before any kernel /// is generated, so compilation can refuse a pass that would exceed the caller's limits. That /// bound is the costs a pass declares before it runs. The bound covers the result object, its /// shared compiler context, and the list of kernels and the map from a scheduled unit of work /// to kernel, sized for `kernel_count` kernels. That context is the object that owns the /// operations and values of the generated kernels. Generated programs, names, generation /// scratch and the analyses it depends on are charged separately. pub fn baseStorageBound(limits: ir.Context.Limits, kernel_count: u64) !u64 { const context = ir.Context.Capacity.derive(limits) catch return error.WorkOverflow; var bytes: u64 = @sizeOf(KernelizationAnalysis) + @alignOf(KernelizationAnalysis); bytes = try accounting.add(bytes, @sizeOf(ir.Context) + @alignOf(ir.Context)); bytes = try accounting.add(bytes, context.storage_bytes); bytes = try accounting.add(bytes, context.storage_alignment.toByteUnits()); const kernels = try accounting.arrayListGrowth(LoweredKernel, kernel_count); bytes = try accounting.add(bytes, kernels); bytes = try accounting.add(bytes, try accounting.hashMapGrowth(usize, usize, kernel_count)); if (bytes > std.math.maxInt(usize)) return error.WorkOverflow; return bytes; } pub fn reserveKernelCapacity(self: *KernelizationAnalysis, count: usize) !void { const map_count = std.math.cast(u32, count) orelse return error.InvalidArtifact; try self.kernels.ensureTotalCapacity(self.allocator, count); try self.work_to_kernel.ensureTotalCapacity(map_count); } pub fn init(allocator: std.mem.Allocator, limits: ir.Context.Limits) !KernelizationAnalysis { const context = try ir.Context.create(allocator, limits); errdefer { context.deinit(allocator); allocator.destroy(context); } dialects.registerChoirDialect(context) catch |err| { return if (err == error.OutOfMemory) error.WorkExhausted else err; }; return .{ .allocator = allocator, .context = context, .kernels = .empty, .work_to_kernel = std.AutoHashMap(usize, usize).init(allocator), }; } pub fn deinit(self: *KernelizationAnalysis) void { for (self.kernels.items) |*kernel| { kernel.deinit(self.allocator); } self.kernels.deinit(self.allocator); self.work_to_kernel.deinit(); self.context.deinit(self.allocator); self.allocator.destroy(self.context); self.* = undefined; } pub fn kernelCount(self: KernelizationAnalysis) usize { return self.kernels.items.len; } pub fn getForWork( self: *const KernelizationAnalysis, work_item_id: usize, ) ?*const LoweredKernel { const index = self.work_to_kernel.get(work_item_id) orelse return null; return &self.kernels.items[index]; } pub fn kernelSummary( self: *const KernelizationAnalysis, kernel_index: usize, ) !GeneratedKernelSummary { const kernel_value = try self.kernelAt(kernel_index); return kernel_value.summary(); } pub fn kernelProgram( self: *const KernelizationAnalysis, kernel_index: usize, ) !*const GeneratedKernelProgram { const kernel_value = try self.kernelAt(kernel_index); return &kernel_value.program; } pub fn kernelSummaryForWork( self: *const KernelizationAnalysis, work_item_id: usize, ) !GeneratedKernelSummary { const kernel_value = self.getForWork(work_item_id) orelse return error.MissingKernelization; return kernel_value.summary(); } pub fn kernelProgramForWork( self: *const KernelizationAnalysis, work_item_id: usize, ) !*const GeneratedKernelProgram { const kernel_value = self.getForWork(work_item_id) orelse return error.MissingKernelization; return &kernel_value.program; } pub fn copyKernelSummaries( self: *const KernelizationAnalysis, result_allocator: std.mem.Allocator, ) !GeneratedKernelSummaries { const items = try result_allocator.alloc(GeneratedKernelSummary, self.kernels.items.len); var copied: usize = 0; errdefer { for (items[0..copied]) |summary| { result_allocator.free(summary.entry_name); } result_allocator.free(items); } for (items, self.kernels.items) |*item, *kernel_value| { item.* = kernel_value.summary(); item.entry_name = try result_allocator.dupe(u8, kernel_value.entry_name); copied += 1; } return .{ .allocator = result_allocator, .items = items, }; } fn kernelAt( self: *const KernelizationAnalysis, kernel_index: usize, ) !*const LoweredKernel { if (kernel_index >= self.kernels.items.len) return error.InvalidIndex; return &self.kernels.items[kernel_index]; }};Source: lib/accy/src/preparation/kernelization/model/product.zig:117
pub const LoweredKernel = struct { work_item_id: usize, entry_name: []u8, program: kernel_program.Program, argument_count: u32, body_fingerprint: u64, dynamic_shared_memory_bytes: u32 = 0, schedule: GeneratedSchedule, launch: ?kernel_schedule.Launch = null, output_fill_pattern: ?u32 = null, scratch_fill_pattern: ?u32 = null, body: LoweredKernelBody = .generic, pub fn deinit(self: *LoweredKernel, allocator: std.mem.Allocator) void { self.program.deinit(); allocator.free(self.entry_name); self.* = undefined; } pub fn runtimeScalarArgumentCount(self: *const LoweredKernel) u32 { var count: u32 = 0; for (self.program.params()) |param| { switch (param) { .scalar => count += 1, .buffer => {}, } } return count; } pub fn requiredDTypes(self: *const LoweredKernel) gpu.DTypeSet { var dtypes: gpu.DTypeSet = .{}; for (self.program.params()) |param| { switch (param) { .scalar => |dtype| dtypes.insert(dtype), .buffer => |buffer| dtypes.insert(buffer.dtype), } } return dtypes; } pub fn launchGeometry(self: *const LoweredKernel) ?choir_abi.LaunchGeometry { const launch_value = self.launch orelse return null; return .{ .grid = launch_value.grid, .threadgroup = launch_value.block, .dynamic_shared_memory_bytes = self.dynamic_shared_memory_bytes, }; } pub fn summary(self: *const LoweredKernel) GeneratedKernelSummary { return .{ .work_item_id = self.work_item_id, .entry_name = self.entry_name, .argument_count = self.argument_count, .body_fingerprint = self.body_fingerprint, .dynamic_shared_memory_bytes = self.dynamic_shared_memory_bytes, .schedule = self.schedule, .launch_geometry = self.launchGeometry(), }; }};Source: lib/accy/src/preparation/kernelization/model/product.zig:464
pub const ReductionDescription = struct { kind: ReductionKind, input_dtype: choir_abi.DType, output_dtype: choir_abi.DType, dims: ReductionStaticDims, init: ReductionInit,};Source: lib/accy/src/preparation/kernelization/model/product.zig:459
pub const ReductionInit = union(enum) { constant: ReductionInitValue, input_buffer,};Source: lib/accy/src/preparation/kernelization/model/product.zig:452
pub const ReductionInitValue = union(enum) { f32: f32, i32: i32, u32: u32, f16: f16,};Source: lib/accy/src/preparation/kernelization/model/product.zig:446
pub const ReductionKind = enum { sum, max, min,};Source: lib/accy/src/preparation/kernelization/model/product.zig:436
pub const ReductionStaticDims = struct { input_rank: u8, axis: u8, input_element_count: u32, output_element_count: u32, rows: u32 = 1, cols: u32 = 1, inner: u32 = 1,};Source: lib/accy/src/preparation/kernelization/model/product.zig:40
pub const ShapeKernel = enum { broadcast_in_dim, iota, reshape, transpose, slice, pad, concatenate, gather, scatter,};Source: lib/accy/src/preparation/kernelization/model/outline.zig:7
pub const kernel_outline_plan_analysis_name = "accy-choir-kernel-outline-plan";Source: lib/accy/src/preparation/kernelization/model/product.zig:472
pub fn addKernel(analysis: *KernelizationAnalysis, kernel: LoweredKernel) !void { const index = analysis.kernels.items.len; try analysis.work_to_kernel.put(kernel.work_item_id, index); errdefer _ = analysis.work_to_kernel.remove(kernel.work_item_id); try analysis.kernels.append(analysis.allocator, kernel);}Source: lib/accy/src/preparation/kernelization/model/product.zig:405
pub fn dotGeneralBlockTileFor(desc: DotGeneralDescription) ?DotGeneralBlockTile { if (desc.input_dtype != .f32 or desc.output_dtype != .f32) return null; if (desc.dims.k >= 128 and blockTileFits(wide_block_tile, desc.dims, wide_block_tile_min_blocks)) return wide_block_tile; var tile = DotGeneralBlockTile{ .stages = 4 }; if (!blockTileFits(tile, desc.dims, block_tile_min_blocks)) return null; if (desc.dims.batch == 1) { const tiles = (desc.dims.m / tile.bm) * (desc.dims.n / tile.bn); while (tile.splits < split_k_max) { const doubled = tile.splits * 2; if (tiles * tile.splits >= split_k_target_blocks) break; if (desc.dims.k % doubled != 0) break; const chunk = desc.dims.k / doubled; if (chunk % tile.bk != 0 or chunk < 2 * tile.bk) break; tile.splits = doubled; } } return tile;}Source: lib/accy/src/preparation/kernelization/model/product.zig:376
pub fn dotGeneralMmaTileFor(desc: DotGeneralDescription) ?DotGeneralMmaTile { if (desc.input_dtype != .f32 or desc.output_dtype != .f32) return null; var tile = DotGeneralMmaTile{}; if (!tile.exact(desc.dims)) return null; const blocks = @as(u64, desc.dims.batch) * (desc.dims.m / tile.bm) * (desc.dims.n / tile.bn); if (blocks < mma_pipeline_max_blocks) { tile.stages = 2; } if (desc.dims.batch == 1 and blocks < 32) { while (tile.splits < split_k_max) { const doubled = tile.splits * 2; if (blocks * tile.splits >= 128) break; if (desc.dims.k % doubled != 0) break; const chunk = desc.dims.k / doubled; if (chunk % (2 * @as(u64, tile.bk)) != 0 or chunk < 4 * @as(u64, tile.bk)) break; tile.splits = doubled; } } return tile;}Source: lib/accy/src/preparation/kernelization/model/product.zig:479
pub fn dynamicSharedMemoryBytes(module: *ir.Operation) gpu.BackendError!u32 { var state = DynamicSharedMemoryState{}; _ = module.walk(.{ .order = .pre_order }, &state, DynamicSharedMemoryState.visit) catch |err| switch (err) { error.OutOfMemory => return error.OutOfMemory, error.InvalidArtifact => return error.InvalidArtifact, else => return error.InvalidArtifact, }; return state.bytes;}Source: lib/accy/src/preparation/kernelization/model/product.zig:351
pub fn reductionAtomicPlanFor( dims: ReductionStaticDims, kind: ReductionKind, input_dtype: choir_abi.DType, init_is_constant: bool,) ?ReductionAtomicPlan { if (dims.output_element_count != 1) return null; if (dims.input_element_count < reduction_atomic_min_extent) return null; if (kind != .sum) return null; if (!init_is_constant) return null; switch (input_dtype) { .f32, .i32, .u32 => {}, else => return null, } const threads = reduction_single_block_threads; const per_block = @as(u64, threads) * reduction_atomic_target_chain; const wanted = (dims.input_element_count + per_block - 1) / per_block; const blocks: u32 = @intCast(@min(@max(wanted, 1), reduction_atomic_max_blocks)); return .{ .threads = threads, .blocks = blocks };}Source: lib/accy/src/preparation/kernelization/model/product.zig:339
pub fn reductionSingleBlockThreads(dims: ReductionStaticDims) ?u32 { if (dims.output_element_count != 1) return null; if (dims.input_element_count < reduction_single_block_min_extent) return null; return reduction_single_block_threads;}Source: lib/accy/src/preparation/kernelization/model/product.zig:333
pub fn reductionWarpRowsThreads(dims: ReductionStaticDims) ?u32 { if (dims.input_rank != 2 or dims.axis != 1) return null; if (dims.cols < reduction_warp_rows_min_cols) return null; return reduction_warp_rows_threads;}Source: lib/accy/src/preparation/kernelization/model/product.zig:328
pub const reduction_single_block_threads: u32 = 256;Source: lib/accy/src/preparation/kernelization/model/product.zig:330
pub const reduction_warp_rows_threads: u32 = 256;Source: lib/accy/src/preparation/kernelization/model/outline.zig:9
Source: lib/accy/src/preparation/kernelization/model/product.zig:326
Source: lib/accy/src/preparation/kernelization/model/product.zig:372
Source: lib/accy/src/preparation/kernelization/model/product.zig:318
Source: lib/accy/src/preparation/kernelization/model/product.zig:109
Source: lib/accy/src/preparation/kernelization/model/product.zig:113
Source: lib/accy/src/preparation/kernelization/model/product.zig:105
Source: lib/accy/src/preparation/kernelization/model/product.zig:54
Source: lib/accy/src/preparation/kernelization/model/product.zig:52
Source: lib/accy/src/preparation/kernelization/model/product.zig:111
Source: lib/accy/src/preparation/kernelization/model/product.zig:345
Source: lib/accy/src/preparation/kernelization/model/product.zig:115
Source: lib/accy/src/preparation/kernelization/model/product.zig:103
Source: lib/accy/src/preparation/kernelization/model/product.zig:107
Source: lib/accy/src/preparation/kernelization/model/root.zig
const product = @import("product.zig");const outline = @import("outline.zig");pub const kernel_outline_plan_analysis_name = outline.kernel_outline_plan_analysis_name;pub const KernelOutlineKind = outline.KernelOutlineKind;pub const KernelOutline = outline.KernelOutline;pub const KernelOutlinePlanAnalysis = outline.KernelOutlinePlanAnalysis;pub const ElementwiseKernel = product.ElementwiseKernel;pub const ShapeKernel = product.ShapeKernel;pub const GeneratedScheduleKind = product.GeneratedScheduleKind;pub const GeneratedSchedule = product.GeneratedSchedule;pub const GeneratedKernelProgram = product.GeneratedKernelProgram;pub const GeneratedKernelSummary = product.GeneratedKernelSummary;pub const GeneratedKernelSummaries = product.GeneratedKernelSummaries;pub const RowPipelinePlan = product.RowPipelinePlan;pub const FlashAttentionPlan = product.FlashAttentionPlan;pub const ScanPlan = product.ScanPlan;pub const ElementwiseRank2Plan = product.ElementwiseRank2Plan;pub const LoweredKernelBody = product.LoweredKernelBody;pub const ElementwiseVectorPlan = product.ElementwiseVectorPlan;pub const ReductionWarpRowsPlan = product.ReductionWarpRowsPlan;pub const LoweredKernel = product.LoweredKernel;pub const KernelizationAnalysis = product.KernelizationAnalysis;pub const DotGeneralStaticDims = product.DotGeneralStaticDims;pub const DotGeneralDescription = product.DotGeneralDescription;pub const DotGeneralBlockTile = product.DotGeneralBlockTile;pub const reduction_single_block_threads = product.reduction_single_block_threads;pub const reduction_warp_rows_threads = product.reduction_warp_rows_threads;pub const reductionWarpRowsThreads = product.reductionWarpRowsThreads;pub const reductionSingleBlockThreads = product.reductionSingleBlockThreads;pub const ReductionAtomicPlan = product.ReductionAtomicPlan;pub const reductionAtomicPlanFor = product.reductionAtomicPlanFor;pub const DotGeneralMmaTile = product.DotGeneralMmaTile;pub const dotGeneralMmaTileFor = product.dotGeneralMmaTileFor;pub const dotGeneralBlockTileFor = product.dotGeneralBlockTileFor;pub const ReductionStaticDims = product.ReductionStaticDims;pub const ReductionKind = product.ReductionKind;pub const ReductionInitValue = product.ReductionInitValue;pub const ReductionInit = product.ReductionInit;pub const ReductionDescription = product.ReductionDescription;pub const addKernel = product.addKernel;pub const dynamicSharedMemoryBytes = product.dynamicSharedMemoryBytes;Source: lib/accy/src/preparation/kernelization/root.zig:1
pub const product = @import("model/root.zig");Audit
| Definitions | 64 |
|---|---|
| Public names | 124 |
| Members | 94 |
| Version | 26.7.0 |
| Revision | daab053ee433 |