minseok
π Release BioPhys 6.0 Grand Master: 16GB (14.89GB) Gemma-4 100% Devour, Ecosystem Evolution, Solar MoE, SNN Autoregressive SDK, Dynamic PhaseVM
be99550 | // π μΈλΆ λΌμ΄λΈλ¬λ¦¬(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 } } | |
| } | |
| fn next_u32(&mut self) -> u32 { | |
| let mut x = self.state; | |
| x ^= x << 13; | |
| x ^= x >> 17; | |
| x ^= x << 5; | |
| self.state = x; | |
| x | |
| } | |
| fn next_f32(&mut self) -> f32 { | |
| (self.next_u32() & 0x00FFFFFF) as f32 / 16777216.0 * 2.0 - 1.0 // -1.0 ~ 1.0 | |
| } | |
| } | |
| // 2. 8λ μ΄μ° μμ μ²΄κ³ (μμ λ§€ν) | |
| 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 { | |
| 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, | |
| } | |
| } | |
| 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<f32>, | |
| pub topsoil: Vec<Phase8>, | |
| } | |
| impl PureCustomEngine { | |
| pub fn new(size: usize, seed: u32) -> Self { | |
| let mut rng = FastRng::new(seed); | |
| let total = size * size; | |
| let bedrock: Vec<f32> = (0..total).map(|_| rng.next_f32() * 0.5).collect(); | |
| let topsoil: Vec<Phase8> = (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!("============================================================"); | |
| } | |