pub fn persistent_fixpoint_program(
transfer_body: Vec<Node>,
current: &str,
next: &str,
changed: &str,
words: u32,
max_iterations: u32,
) -> ProgramExpand description
Build a persistent-fixpoint Program around a caller-supplied transfer body.
The generated program runs transfer_body, ping-pongs current and next,
and stops when the convergence flag reads zero or max_iterations is
reached. Runtime and driver crates call this self-substrate wrapper instead
of depending on the primitive catalog directly.
§Convergence-flag form
words sizes the widest buffer this wrapper declares, and
dispatch_element_count_for_program
(vyre-driver/src/program_walks/dispatch_params.rs:19) sizes an
atomic-carrying program’s launch from its widest declared buffer, so words
is the launch span and it selects the harness:
words <= PERSISTENT_FIXPOINT_WORKGROUP_SIZE[0]: one workgroup covers the launch, sopersistent_fixpointruns with its single sharedchanged[0]word and stops when that word reads zero. The word is cleared by a plain store fenced only by a workgroup-scope barrier; with one group the fence is incidentally grid-wide, so the clear cannot race theatomic_orthat sets the flag.wordsabove that width:persistent_fixpoint_grid, which never clears the flag, gives each iteration its ownchangedword, and separates waves withMemoryOrdering::GridSync. The single-word form is limited to one workgroup precisely because its clear and its set are unordered across groups: group 0’s clear can erase another group’s set, that group then reads zero and returns early with unconverged state, and the flag the host reads afterwards reports a convergence no group agreed to.
The caller supplies changed, so it must be max_iterations zero-filled
words once words exceeds one workgroup width and one word at or below it.
This wrapper can only see the buffers the harness declares. A caller whose
transfer_body reads buffers wider than words, or that widens the launch
through DispatchConfig, owns that span itself.