// πŸš€ μ™ΈλΆ€ 라이브러리(Crate) μ „ν˜€ 없이 ν‘œμ€€ 라이브러리(std)만으둜 λ°‘λ°”λ‹₯λΆ€ν„° 직접 κ΅¬ν˜„ν•œ 순수 μ—”μ§„ (src/bin/pure_custom_engine.rs) use std::time::Instant; use std::thread; // 1. 순수 λΉ„νŠΈ μ‹œν”„νŠΈ 기반 μ΄ˆκ³ μ† 자체 λ‚œμˆ˜ 생성기 (Xorshift32 - μ™ΈλΆ€ rand 라이브러리 배제) struct FastRng { state: u32, } impl FastRng { fn new(seed: u32) -> Self { FastRng { state: if seed == 0 { 0x12345678 } else { seed } } } #[inline(always)] fn next_u32(&mut self) -> u32 { let mut x = self.state; x ^= x << 13; x ^= x >> 17; x ^= x << 5; self.state = x; x } #[inline(always)] fn next_f32(&mut self) -> f32 { (self.next_u32() & 0x00FFFFFF) as f32 / 16777216.0 * 2.0 - 1.0 // -1.0 ~ 1.0 } } // 2. 8λŒ€ 이산 μœ„μƒ 체계 (순수 λ§€ν•‘) #[derive(Copy, Clone, Debug, PartialEq)] #[repr(u8)] pub enum Phase8 { HyperInhibit = 0, // -2.0 Inhibit = 1, // -1.0 SubInhibit = 2, // -0.5 NegZero = 3, // -0.0 PosZero = 4, // +0.0 SubExcite = 5, // +0.5 Excite = 6, // +1.0 HyperExcite = 7, // +2.0 } impl Phase8 { #[inline(always)] pub fn to_weight(self) -> f32 { match self { Phase8::HyperInhibit => -2.0, Phase8::Inhibit => -1.0, Phase8::SubInhibit => -0.5, Phase8::NegZero => -0.01, Phase8::PosZero => 0.01, Phase8::SubExcite => 0.5, Phase8::Excite => 1.0, Phase8::HyperExcite => 2.0, } } #[inline(always)] pub fn from_field(f: f32) -> Self { if f <= -1.5 { Phase8::HyperInhibit } else if f <= -0.75 { Phase8::Inhibit } else if f <= -0.25 { Phase8::SubInhibit } else if f <= 0.0 { Phase8::NegZero } else if f <= 0.25 { Phase8::PosZero } else if f <= 0.75 { Phase8::SubExcite } else if f <= 1.5 { Phase8::Excite } else { Phase8::HyperExcite } } } // 3. μ™ΈλΆ€ 크레이트 μ—†λŠ” 순수 ν‘œμ€€ λ©€ν‹°μŠ€λ ˆλ“œ λ³΅μž‘κ³„ μ—”μ§„ pub struct PureCustomEngine { pub size: usize, pub bedrock: Vec, pub topsoil: Vec, } impl PureCustomEngine { pub fn new(size: usize, seed: u32) -> Self { let mut rng = FastRng::new(seed); let total = size * size; let bedrock: Vec = (0..total).map(|_| rng.next_f32() * 0.5).collect(); let topsoil: Vec = (0..total).map(|_| Phase8::from_field(rng.next_f32() * 2.0)).collect(); PureCustomEngine { size, bedrock, topsoil } } /// ν‘œμ€€ 라이브러리 std::thread::scope 기반의 순수 λ©€ν‹°μ½”μ–΄ 병렬 κ°±μ‹  pub fn step_native_multithread(&mut self, num_threads: usize) -> f32 { let size = self.size; let total = size * size; let chunk_rows = (size + num_threads - 1) / num_threads; let prev_topsoil = &self.topsoil; let bedrock = &self.bedrock; let (next_topsoil, total_energy) = thread::scope(|s| { let mut handles = Vec::with_capacity(num_threads); for thread_id in 0..num_threads { let start_y = thread_id * chunk_rows; let end_y = (start_y + chunk_rows).min(size); if start_y >= size { break; } handles.push(s.spawn(move || { let s_dim = size as i32; let mut local_chunk = Vec::with_capacity((end_y - start_y) * size); let mut local_energy_sum = 0.0f32; for y in start_y..end_y { for x in 0..size { let idx = y * size + x; let u = ((y as i32 - 1 + s_dim) % s_dim * s_dim + x as i32) as usize; let d = ((y as i32 + 1) % s_dim * s_dim + x as i32) as usize; let l = (y as i32 * s_dim + (x as i32 - 1 + s_dim) % s_dim) as usize; let r = (y as i32 * s_dim + (x as i32 + 1) % s_dim) as usize; let neighbor_e = ( prev_topsoil[u].to_weight() + prev_topsoil[d].to_weight() + prev_topsoil[l].to_weight() + prev_topsoil[r].to_weight() ) * 0.25; let local_f = neighbor_e + bedrock[idx]; local_chunk.push(Phase8::from_field(local_f)); local_energy_sum += local_f.abs(); } } (local_chunk, local_energy_sum) })); } let mut combined_topsoil = Vec::with_capacity(total); let mut total_e = 0.0f32; for h in handles { let (chunk, e) = h.join().unwrap(); combined_topsoil.extend(chunk); total_e += e; } (combined_topsoil, total_e) }); self.topsoil = next_topsoil; total_energy / (total as f32) } } fn main() { println!("============================================================"); println!(" ⚑ μ™ΈλΆ€ 라이브러리(Crate) 제둜(0): 순수 λ°‘λ°”λ‹₯ κ΅¬ν˜„ μ—”μ§„"); println!("============================================================\n"); let grid_size = 512; // 262,144 λ…Έλ“œ let threads = 16; println!("βš™οΈ [순수 자체 κ΅¬ν˜„ μŠ€νŽ™] 512x512 (262K λ…Έλ“œ) | 자체 Xorshift λ‚œμˆ˜ | std::thread::scope λ©€ν‹°μŠ€λ ˆλ“œ ({}μŠ€λ ˆλ“œ)", threads); let mut engine = PureCustomEngine::new(grid_size, 42); let total_ticks = 10; let start_time = Instant::now(); for tick in 1..=total_ticks { let t_start = Instant::now(); let avg_e = engine.step_native_multithread(threads); let t_elapsed = t_start.elapsed().as_secs_f64() * 1000.0; println!("⏱️ [Tick {:02}] 평균 계면 μ—λ„ˆμ§€: {:.4} | μ†Œμš” μ‹œκ°„: {:.2} ms", tick, avg_e, t_elapsed); } let total_dur = start_time.elapsed().as_secs_f64(); let total_updates = (grid_size * grid_size * total_ticks) as f64; let throughput = (total_updates / total_dur) / 1e6; println!("\n============================================================"); println!(" πŸ“Š 순수 자체 κ΅¬ν˜„ 벀치마크 κ²°κ³Ό (Zero-Dependency)"); println!("============================================================"); println!(" ⏱️ 총 μ—°μ‚° μ‹œκ°„ : {:.4} 초", total_dur); println!(" πŸ”„ 총 κ°±μ‹  μ…€ 수 : {:.2} Million Cells", total_updates / 1e6); println!(" ⚑ 순수 자체 μŠ€λ ˆλ“œ 속도 : {:.2} MCell/sec", throughput); println!("============================================================"); }