pairs_scale/
pairs_scale.rs1use std::time::Instant;
12
13use linkcell::{pairs_within, Cell};
14
15fn env_usize(key: &str, default: usize) -> usize {
16 std::env::var(key)
17 .ok()
18 .and_then(|s| s.parse().ok())
19 .unwrap_or(default)
20}
21
22fn fill(n: usize) -> Vec<[f64; 3]> {
23 let boxl = 18.0;
24 let m = (n as f64).cbrt().ceil() as usize;
25 let mut xyz = Vec::with_capacity(n);
26 let mut count = 0usize;
27 'outer: for iz in 0..m {
28 for iy in 0..m {
29 for ix in 0..m {
30 if count >= n {
31 break 'outer;
32 }
33 xyz.push([
34 (ix as f64 + 0.5) * boxl / m as f64,
35 (iy as f64 + 0.5) * boxl / m as f64,
36 (iz as f64 + 0.5) * boxl / m as f64,
37 ]);
38 count += 1;
39 }
40 }
41 }
42 xyz
43}
44
45fn shuffle(xyz: &mut [[f64; 3]], seed: u64) {
47 let mut s = seed.max(1);
48 for i in (1..xyz.len()).rev() {
49 s ^= s << 13;
50 s ^= s >> 7;
51 s ^= s << 17;
52 xyz.swap(i, (s % (i as u64 + 1)) as usize);
53 }
54}
55
56fn main() {
57 let n = env_usize("PAIRS_N", 4096);
58 let reps = env_usize("PAIRS_REPS", 5).max(1);
59 let half = std::env::var("PAIRS_HALF").ok().as_deref() == Some("1");
60 let hint = std::env::var("PAIRS_HINT")
61 .ok()
62 .and_then(|s| s.parse().ok());
63 let threads = std::env::var("RAYON_NUM_THREADS").unwrap_or_else(|_| "default".to_string());
64 let mut xyz = fill(n);
65 if let Some(seed) = std::env::var("PAIRS_SHUFFLE")
66 .ok()
67 .and_then(|s| s.parse().ok())
68 {
69 shuffle(&mut xyz, seed);
70 }
71 let cell = Cell::ortho(18.0, 18.0, 18.0).expect("box");
72 linkcell::pop_engage();
73 linkcell::pop_prepare();
74 let mut pairs = Vec::new();
75 let mut early = Vec::new();
76 for _ in 0..3 {
77 let t = Instant::now();
78 pairs = pairs_within(&xyz, &cell, 4.0, None, hint, half).expect("pairs");
79 early.push(t.elapsed().as_secs_f64() * 1e3);
80 }
81 linkcell::pop_reset();
82 let t0 = Instant::now();
83 let mut acc = 0usize;
84 for _ in 0..reps {
85 let got = pairs_within(&xyz, &cell, 4.0, None, hint, half).expect("pairs");
86 acc += got.len();
87 }
88 let wall_ns = t0.elapsed().as_nanos() as u64;
89 let ms = wall_ns as f64 / 1e6;
90 println!(
91 "n={} half={} hint={:?} pairs={} cold={:.3} call2={:.3} call3={:.3} reps={} ms_per={:.4} acc={}",
92 xyz.len(),
93 half as u8,
94 hint,
95 pairs.len(),
96 early[0],
97 early[1],
98 early[2],
99 reps,
100 ms / reps as f64,
101 acc
102 );
103 let useful = linkcell::pop_snapshot();
104 let (lb, ce, pe) = linkcell::pop_efficiencies(&useful, wall_ns);
105 let list = useful
106 .iter()
107 .map(|ns| ns.to_string())
108 .collect::<Vec<_>>()
109 .join(",");
110 println!(
111 "pop shape=pairs-{n}-h{} threads={threads} n={n} reps={reps} wall_ns={wall_ns} useful_ns={list} lb={lb:.4} ce={ce:.4} pe={pe:.4}",
112 half as u8
113 );
114}