pub(crate) fn subset_closure_resident_plan_with_scratch(
pipeline: &dyn vyre::CompiledPipeline,
graph: &crate::fixed_point_resident::FixedPointResidentGraph,
seed_bits: &[u32],
max_iterations: u32,
config: &vyre::DispatchConfig,
scratch: &mut crate::fixed_point_scratch::FixedPointScratch,
) -> Result<Vec<u32>, String> {
let mut result = crate::staging_reserve::reserved_vec(
crate::dispatch_decode::bitset_word_capacity(
"points_to subset_closure resident result",
graph.node_count(),
)?,
"fixed-point result word",
)?;
subset_closure_resident_plan_with_scratch_into(
pipeline,
graph,
seed_bits,
max_iterations,
config,
scratch,
&mut result,
)?;
Ok(result)
}
pub(crate) fn subset_closure_resident_plan_with_scratch_into(
pipeline: &dyn vyre::CompiledPipeline,
graph: &crate::fixed_point_resident::FixedPointResidentGraph,
seed_bits: &[u32],
max_iterations: u32,
config: &vyre::DispatchConfig,
scratch: &mut crate::fixed_point_scratch::FixedPointScratch,
result: &mut Vec<u32>,
) -> Result<(), String> {
graph.require_kind(
crate::fixed_point_graph::FixedPointAnalysisKind::PointsToSubset,
"subset_closure_resident_plan_with_scratch_into",
)?;
crate::dispatch_decode::require_positive_iterations(
"points_to subset_closure_via",
max_iterations,
)?;
let words = crate::dispatch_decode::bitset_word_capacity(
"points_to subset_closure resident",
graph.node_count(),
)?;
crate::dispatch_decode::require_bitset_words("points_to subset_closure_via", seed_bits, words)?;
crate::dispatch_decode::require_bitset_tail_clear(
"points_to subset_closure_via",
seed_bits,
graph.node_count(),
)?;
scratch.prepare_frontier_words(words, seed_bits)?;
scratch.begin_frontier_density(graph.node_count());
scratch.prepare_grid_dispatch_config(config, [graph.node_count().max(1), 1, 1]);
scratch.prepare_next_words(words)?;
for _ in 0..max_iterations {
crate::dispatch_decode::try_pack_u32_into(&scratch.frontier_words, &mut scratch.frontier_bytes, "weir u32 byte staging")?;
graph.resources_with_frontier_into(&scratch.frontier_bytes, &mut scratch.resources)?;
pipeline
.dispatch_persistent_handles_into(
&scratch.resources,
&scratch.dispatch_config,
&mut scratch.outputs,
)
.map_err(|error| error.to_string())?;
crate::dispatch_decode::unpack_only_exact_u32_into(
&scratch.outputs,
"points_to subset_closure_via",
"points-to frontier",
words,
&mut scratch.next,
)?;
crate::dispatch_decode::require_bitset_tail_clear(
"points_to subset_closure_via output",
&scratch.next,
graph.node_count(),
)?;
scratch.record_decoded_frontier_transition();
if crate::fixed_point_scratch::copy_if_converged(
&scratch.next,
&scratch.frontier_words,
result,
)? {
return Ok(());
}
std::mem::swap(&mut scratch.frontier_words, &mut scratch.next);
}
Err(format!(
"points_to subset_closure_via did not converge within {max_iterations} iterations"
))
}
pub fn subset_closure_resident_plan_with_backend_scratch(
backend: &dyn vyre::VyreBackend,
pipeline: &dyn vyre::CompiledPipeline,
graph: &crate::fixed_point_resident::FixedPointResidentGraph,
seed_bits: &[u32],
max_iterations: u32,
config: &vyre::DispatchConfig,
scratch: &mut crate::fixed_point_scratch::FixedPointScratch,
) -> Result<Vec<u32>, String> {
let mut result = crate::staging_reserve::reserved_vec(
crate::dispatch_decode::bitset_word_capacity(
"points_to subset_closure resident backend result",
graph.node_count(),
)?,
"fixed-point result word",
)?;
subset_closure_resident_plan_with_backend_scratch_into(
backend,
pipeline,
graph,
seed_bits,
max_iterations,
config,
scratch,
&mut result,
)?;
Ok(result)
}
pub fn subset_closure_resident_plan_with_backend_scratch_into(
backend: &dyn vyre::VyreBackend,
pipeline: &dyn vyre::CompiledPipeline,
graph: &crate::fixed_point_resident::FixedPointResidentGraph,
seed_bits: &[u32],
max_iterations: u32,
config: &vyre::DispatchConfig,
scratch: &mut crate::fixed_point_scratch::FixedPointScratch,
result: &mut Vec<u32>,
) -> Result<(), String> {
graph.require_kind(
crate::fixed_point_graph::FixedPointAnalysisKind::PointsToSubset,
"subset_closure_resident_plan_with_backend_scratch_into",
)?;
crate::dispatch_decode::require_positive_iterations(
"points_to subset_closure_via",
max_iterations,
)?;
let words = crate::dispatch_decode::bitset_word_capacity(
"points_to subset_closure resident",
graph.node_count(),
)?;
crate::dispatch_decode::require_bitset_words("points_to subset_closure_via", seed_bits, words)?;
crate::dispatch_decode::require_bitset_tail_clear(
"points_to subset_closure_via",
seed_bits,
graph.node_count(),
)?;
scratch.prepare_frontier_words(words, seed_bits)?;
let frontier_byte_len = words.checked_mul(4).ok_or_else(|| {
"points_to subset_closure_via resident frontier byte length overflow. Fix: shard the graph before GPU dispatch.".to_string()
})?;
let frontier_in = backend
.allocate_resident(frontier_byte_len)
.map_err(|error| error.to_string())?;
let frontier_out = match backend.allocate_resident(frontier_byte_len) {
Ok(resource) => resource,
Err(error) => {
let _ = backend.free_resident(frontier_in);
return Err(error.to_string());
}
};
let run_result = subset_closure_resident_plan_with_frontier_resources_into(
backend,
pipeline,
graph,
&frontier_in,
&frontier_out,
max_iterations,
config,
scratch,
result,
);
let free_in = backend
.free_resident(frontier_in)
.map_err(|error| error.to_string());
let free_out = backend
.free_resident(frontier_out)
.map_err(|error| error.to_string());
match (run_result, free_in, free_out) {
(Err(error), _, _) => Err(error),
(Ok(_), Err(error), _) | (Ok(_), _, Err(error)) => Err(error),
(Ok(()), Ok(()), Ok(())) => Ok(()),
}
}
pub fn subset_closure_resident_plan_with_reusable_frontier_scratch(
backend: &dyn vyre::VyreBackend,
pipeline: &dyn vyre::CompiledPipeline,
graph: &crate::fixed_point_resident::FixedPointResidentGraph,
seed_bits: &[u32],
max_iterations: u32,
config: &vyre::DispatchConfig,
scratch: &mut crate::fixed_point_scratch::FixedPointScratch,
resident_frontier: &mut crate::fixed_point_resident::FixedPointResidentFrontierScratch,
) -> Result<Vec<u32>, String> {
let mut result = crate::staging_reserve::reserved_vec(
crate::dispatch_decode::bitset_word_capacity(
"points_to subset_closure resident reusable result",
graph.node_count(),
)?,
"fixed-point result word",
)?;
subset_closure_resident_plan_with_reusable_frontier_scratch_into(
backend,
pipeline,
graph,
seed_bits,
max_iterations,
config,
scratch,
resident_frontier,
&mut result,
)?;
Ok(result)
}
pub fn subset_closure_resident_plan_with_reusable_frontier_scratch_sequence_window(
backend: &dyn vyre::VyreBackend,
program: &vyre::ir::Program,
graph: &crate::fixed_point_resident::FixedPointResidentGraph,
seed_bits: &[u32],
max_iterations: u32,
scratch: &mut crate::fixed_point_scratch::FixedPointScratch,
resident_frontier: &mut crate::fixed_point_resident::FixedPointResidentFrontierScratch,
) -> Result<Vec<u32>, String> {
let mut result = crate::staging_reserve::reserved_vec(
crate::dispatch_decode::bitset_word_capacity(
"points_to subset_closure resident sequence result",
graph.node_count(),
)?,
"fixed-point result word",
)?;
subset_closure_resident_plan_with_reusable_frontier_scratch_sequence_window_into(
backend,
program,
graph,
seed_bits,
max_iterations,
scratch,
resident_frontier,
&mut result,
)?;
Ok(result)
}
pub fn subset_closure_resident_plan_with_reusable_frontier_scratch_into(
backend: &dyn vyre::VyreBackend,
pipeline: &dyn vyre::CompiledPipeline,
graph: &crate::fixed_point_resident::FixedPointResidentGraph,
seed_bits: &[u32],
max_iterations: u32,
config: &vyre::DispatchConfig,
scratch: &mut crate::fixed_point_scratch::FixedPointScratch,
resident_frontier: &mut crate::fixed_point_resident::FixedPointResidentFrontierScratch,
result: &mut Vec<u32>,
) -> Result<(), String> {
graph.require_kind(
crate::fixed_point_graph::FixedPointAnalysisKind::PointsToSubset,
"subset_closure_resident_plan_with_reusable_frontier_scratch_into",
)?;
crate::dispatch_decode::require_positive_iterations(
"points_to subset_closure_via",
max_iterations,
)?;
let words = crate::dispatch_decode::bitset_word_capacity(
"points_to subset_closure resident",
graph.node_count(),
)?;
crate::dispatch_decode::require_bitset_words("points_to subset_closure_via", seed_bits, words)?;
crate::dispatch_decode::require_bitset_tail_clear(
"points_to subset_closure_via",
seed_bits,
graph.node_count(),
)?;
scratch.prepare_frontier_words(words, seed_bits)?;
let frontier_byte_len = words.checked_mul(4).ok_or_else(|| {
"points_to subset_closure_via resident frontier byte length overflow. Fix: shard the graph before GPU dispatch.".to_string()
})?;
let (frontier_in, frontier_out) =
resident_frontier.ensure_pair_refs(backend, frontier_byte_len)?;
subset_closure_resident_plan_with_frontier_resources_into(
backend,
pipeline,
graph,
frontier_in,
frontier_out,
max_iterations,
config,
scratch,
result,
)
}
pub fn subset_closure_resident_plan_with_reusable_frontier_scratch_sequence_window_into(
backend: &dyn vyre::VyreBackend,
program: &vyre::ir::Program,
graph: &crate::fixed_point_resident::FixedPointResidentGraph,
seed_bits: &[u32],
max_iterations: u32,
scratch: &mut crate::fixed_point_scratch::FixedPointScratch,
resident_frontier: &mut crate::fixed_point_resident::FixedPointResidentFrontierScratch,
result: &mut Vec<u32>,
) -> Result<(), String> {
crate::fixed_point_resident_sequence::run_resident_sequence_window_into(
backend,
program,
graph,
seed_bits,
max_iterations,
scratch,
resident_frontier,
result,
crate::fixed_point_graph::FixedPointAnalysisKind::PointsToSubset,
"points_to subset_closure_via sequence-window",
)
}
fn subset_closure_resident_plan_with_frontier_resources_into(
backend: &dyn vyre::VyreBackend,
pipeline: &dyn vyre::CompiledPipeline,
graph: &crate::fixed_point_resident::FixedPointResidentGraph,
frontier_in: &vyre::backend::Resource,
frontier_out: &vyre::backend::Resource,
max_iterations: u32,
config: &vyre::DispatchConfig,
scratch: &mut crate::fixed_point_scratch::FixedPointScratch,
result: &mut Vec<u32>,
) -> Result<(), String> {
let words = scratch.frontier_words.len();
scratch.begin_frontier_density(graph.node_count());
scratch.prepare_grid_dispatch_config(config, [graph.node_count().max(1), 1, 1]);
scratch.prepare_next_words(words)?;
crate::dispatch_decode::try_pack_u32_into(&scratch.frontier_words, &mut scratch.frontier_bytes, "weir u32 byte staging")?;
backend
.upload_resident_many(&[
(frontier_in, scratch.frontier_bytes.as_slice()),
(frontier_out, scratch.frontier_bytes.as_slice()),
])
.map_err(|error| error.to_string())?;
let mut current_frontier = frontier_in;
let mut next_frontier = frontier_out;
for _ in 0..max_iterations {
graph.resources_with_resident_frontier_into(
current_frontier,
next_frontier,
&mut scratch.resources,
)?;
pipeline
.dispatch_persistent_handles_into(
&scratch.resources,
&scratch.dispatch_config,
&mut scratch.outputs,
)
.map_err(|error| error.to_string())?;
crate::dispatch_decode::unpack_only_exact_u32_into(
&scratch.outputs,
"points_to subset_closure_via",
"points-to frontier",
words,
&mut scratch.next,
)?;
crate::dispatch_decode::require_bitset_tail_clear(
"points_to subset_closure_via output",
&scratch.next,
graph.node_count(),
)?;
scratch.record_decoded_frontier_transition();
if crate::fixed_point_scratch::copy_if_converged(
&scratch.next,
&scratch.frontier_words,
result,
)? {
return Ok(());
}
std::mem::swap(&mut scratch.frontier_words, &mut scratch.next);
std::mem::swap(&mut current_frontier, &mut next_frontier);
}
Err(format!(
"points_to subset_closure_via did not converge within {max_iterations} iterations"
))
}