github ↗
docs menu

Module Tolk.Realize

The calls of a schedule, and the compilation of their kernels.

A schedule is an Op.t.Linear of calls (Schedule). This module reads what a call does (its buffers, its variables, what it writes, its name and its cost) and compiles every kernel a schedule calls, in parallel. Running them is the engine's.

Calls

#val get_call_arg_uops : Ops.t -> Ops.t list

get_call_arg_uops call is the buffer arguments of call: its arguments without its scalar ones, the variables it binds and the values it passes.

#val get_call_kernel_args : Ops.t -> Ops.t -> Ops.t list

get_call_kernel_args call prg is what call passes for each parameter of the program prg (Shape.kernel_params), in the order the program takes them: for a buffer, call's argument in its slot; for a scalar parameter that a slot names, call's argument in that slot, an expression of the loops around call; for a named variable, the variable call binds to its name, whose value holds where a run does not bind the name, or else the variable, at slot -1, that a run binds by name. The bounds of a split program's block (Ops.kernel_info.split) are those of its whole loop.

Raises Invalid_argument if prg is not a linearized program.

#val call_values : Ops.t -> Ops.t -> Ops.t

call_values call u is u, a launch size, a split's iterations or an estimate of call's program, with each scalar parameter replaced by what call gives it: a nameless parameter, call's argument in its slot; a variable, the variable call binds to its name, or else the variable, at slot -1, that a run binds by name.

Raises Failure if a nameless parameter's slot lies past call's arguments, and Invalid_argument if it is negative.

#val get_call_outs_ins : Ops.t -> int list * int list

get_call_outs_ins call is the positions among call's arguments of the buffers it writes and of those it reads: a program's (Ops.program_info.outs and Ops.program_info.ins), ([0], [1]) for a copy, and ([], []) for any other call.

#val get_call_name : ?var_vals:(string * int) list -> Ops.t -> Ops.t list -> string

get_call_name ~var_vals call bufs is how diagnostics name call, whose buffers are bufs: a program's kernel name, as its kernel gives it, or, for a copy, "copy S, D <- E" in yellow, where S is the size copied with the variables of var_vals (default []) replaced by their values, and D and E the first seven characters of the destination's and the source's devices.

Raises Invalid_argument for any other call.

#val estimate_uop : Ops.t -> Ops.estimates

estimate_uop call is the cost of call, seen through its Op.t.Afters: a program's kernel estimates and, for a copy, its bytes as both memory touched and bytes loaded and stored. Any other call costs nothing.

Compiling

#val lower_and_compile : ?search:(int -> Postrange.Scheduler.t -> Postrange.Scheduler.t) -> targets:(string -> Helpers.Target.t) -> Ops.t -> Ops.t

lower_and_compile ~search ~targets linear is linear with the body of each call that is a kernel (Op.t.Sink with Ops.kernel_info), outside the bodies of the calls, replaced by its compiled program (Codegen.to_program), for the renderer Device.renderer picks for the target targets d of the device d of the call's first storage argument (get_call_arg_uops): a kernel's parameters name no device.

A launch (Shape.launch) runs on a target only within what it can run, so it is first split, in order, into launches that fit: a member that fixes its threads or reduces, which may share values between a workgroup's threads through workgroup memory and barriers, joins only members of its own kernel, so that every thread reaches each barrier of the member it runs, and runs alone where the target cannot declare workgroup memory there (Renderer.t.launch_locals); and a launch holds at most Renderer.t.launch_members members, Renderer.t.launch_args arguments and, with Setting.max_kernel_buffers at n above 0, n buffers.

The kernels of one program key (Codegen.program_key) take one program, compiled once: a key whose program this process has made or the disk keeps (Codegen.read) takes it, read on the calling domain, and the others, one kernel of each, are made together in parallel (Codegen.to_programs), except when one of them asks for a beam search: the search times candidates (search), which a concurrent compilation would disturb, so they are then compiled in order. search is Codegen.to_program's beam.

Raises as Codegen.to_program does, Invalid_argument if a kernel's first storage argument names no device or Device.renderer finds no renderer for a target, and Failure if the renderer's compiler's library is missing.

#type kernel = {
  1. #name : string;
    (*

    Its name, as optimisation named it.

    *)
  2. #key : string;
    (*

    Its program key (Codegen.program_key).

    *)
  3. #ast : Ops.t;
    (*

    The sink it was compiled from, before optimisation.

    *)
  4. #renderer : Renderer.t;
    (*

    The renderer it was compiled for.

    *)
  5. #opts : Opt.t list;
    (*

    The optimisations its program applied, in order.

    *)
}

The type for a kernel lower_and_compile compiled.

#val collecting : unit -> bool

collecting () is true on a domain running kernels's function.

#val kernels : (unit -> 'a) -> 'a * kernel list

kernels f is f () and each kernel of each schedule that lower_and_compile compiles on the calling domain while f runs, in order, whether its program was made or kept. A kernels inside f takes the kernels found while it runs. For the suites.

#val compile_linear : ?search:(int -> Postrange.Scheduler.t -> Postrange.Scheduler.t) -> targets:(string -> Helpers.Target.t) -> Ops.t -> Ops.t

compile_linear ~search ~targets linear is the schedule linear, whose devices compile for the targets targets gives, ready to link and run:

  1. when the setting Setting.beam is 1 or more, each kernel that asks for no beam search asks for one of that width;
  2. its kernels are compiled (lower_and_compile, with search).

Each call of the result is a call of a compiled Op.t.Program (a kernel), or of an Op.t.Store of its second argument's storage into its first's (a copy); an Op.t.End of ranges around such calls, which run once for each combination of the ranges' values, the last range varying fastest; or an Op.t.Backedge of a range and a flag around them, which run once per trip of the range while the flag's boolean holds.

Raises as lower_and_compile does.