use super::*;
#[test]
fn resident_solver_polls_changed_flag_before_downloading_final_frontier() {
let dispatch = FakeResidentDispatch::new_with_program_graph_buffers(2);
let prepared = ResidentPreparedIfdsCsr {
shape: IfdsShape {
num_procs: 1,
blocks_per_proc: 33,
facts_per_proc: 1,
edge_count: 0,
},
node_count: 33,
words: 2,
pg_nodes: 0,
row_ptr: 1,
col_idx: 2,
pg_edge_kind_mask: 3,
pg_node_tags: 4,
};
let reached = solve_resident_prepared_via(&dispatch, &prepared, &[(0, 0, 0)], 4)
.expect("fake resident solver should converge");
assert_eq!(reached, vec![0]);
assert_eq!(dispatch.dispatches.get(), 2);
assert_eq!(
*dispatch.downloads.borrow(),
vec![4, 4, 8],
"resident solve must download only changed flags per iteration, then the final frontier once"
);
}
#[test]
fn resident_solver_download_bytes_scale_with_iterations_not_frontier_words() {
let dispatch = FakeResidentDispatch::new_with_program_graph_buffers(6);
let node_count = 32_768;
let words = ifds_words(node_count);
let prepared = ResidentPreparedIfdsCsr {
shape: IfdsShape {
num_procs: 1024,
blocks_per_proc: 32,
facts_per_proc: 1,
edge_count: 0,
},
node_count,
words,
pg_nodes: 0,
row_ptr: 1,
col_idx: 2,
pg_edge_kind_mask: 3,
pg_node_tags: 4,
};
let reached = solve_resident_prepared_via(&dispatch, &prepared, &[(0, 0, 0)], 16)
.expect("fake resident solver should converge");
assert_eq!(reached, vec![0]);
assert_eq!(dispatch.dispatches.get(), 6);
let downloads = dispatch.downloads.borrow();
assert_eq!(downloads.len(), 7);
assert_eq!(&downloads[..6], &[4, 4, 4, 4, 4, 4]);
assert_eq!(downloads[6], words * 4);
let downloaded_before_final: usize = downloads[..6].iter().sum();
assert_eq!(
downloaded_before_final, 24,
"resident solve must poll one u32 changed flag per iteration, not download the frontier"
);
assert!(
dispatch
.uploaded_lengths
.borrow()
.iter()
.any(|&len| len == 4),
"resident solve must explicitly reset the changed flag before each primitive step"
);
}
#[test]
fn resident_many_solver_defaults_to_parallel_batch() {
let dispatch = FakeResidentDispatch::new_with_program_graph_buffers(1);
let prepared = ResidentPreparedIfdsCsr {
shape: IfdsShape {
num_procs: 1,
blocks_per_proc: 4,
facts_per_proc: 1,
edge_count: 0,
},
node_count: 4,
words: 1,
pg_nodes: 0,
row_ptr: 1,
col_idx: 2,
pg_edge_kind_mask: 3,
pg_node_tags: 4,
};
let seed_a = [(0, 0, 0)];
let seed_b = [(0, 1, 0)];
let got =
solve_resident_prepared_many_via(&dispatch, &prepared, &[&seed_a[..], &seed_b[..]], 8)
.expect("fake resident batch solver should converge");
assert_eq!(got, vec![vec![0], vec![1024]]);
assert_eq!(
dispatch.dispatches.get(),
2,
"default multi-query solve must process each seed set through the single-query CUDA release path"
);
assert_eq!(
dispatch.sequence_read_ranges_calls.get(),
0,
"default multi-query solve must avoid the broken resident sequence launcher on CUDA"
);
assert_eq!(
dispatch.buffers.borrow().len(),
7,
"default multi-query solve must allocate one frontier matrix and one changed flag"
);
assert_eq!(
*dispatch.downloads.borrow(),
vec![4, 4, 4, 4],
"default multi-query solve should poll changed flags through the single-query CUDA release path"
);
}