// πŸ₯© μ™ΈλΆ€ κ°€μ€‘μΉ˜ ν…μ„œ 직접 μ„­μ·¨ 및 μƒνƒœ 흑수 μ—”μ§„ (src/bin/ingest_weights.rs) use std::time::Instant; use std::thread; #[derive(Copy, Clone, Debug, PartialEq)] #[repr(u8)] pub enum Phase8 { HyperInhibit = 0, Inhibit = 1, SubInhibit = 2, NegZero = 3, PosZero = 4, SubExcite = 5, Excite = 6, HyperExcite = 7, } 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_raw_weight(w: f32) -> Self { if w <= -1.5 { Phase8::HyperInhibit } else if w <= -0.75 { Phase8::Inhibit } else if w <= -0.25 { Phase8::SubInhibit } else if w <= 0.0 { Phase8::NegZero } else if w <= 0.25 { Phase8::PosZero } else if w <= 0.75 { Phase8::SubExcite } else if w <= 1.5 { Phase8::Excite } else { Phase8::HyperExcite } } } pub struct WeightDigestionEngine { pub size: usize, pub ingested_weights: Vec, pub bedrock: Vec, } impl WeightDigestionEngine { pub fn new(size: usize) -> Self { let total = size * size; WeightDigestionEngine { size, ingested_weights: vec![Phase8::PosZero; total], bedrock: vec![0.0; total], } } /// μ™ΈλΆ€ κ°€μ€‘μΉ˜ ν…μ„œ λ°°μ—΄(100만 개)을 ν†΅μ§Έλ‘œ μ„­μ·¨(Ingest)ν•˜μ—¬ 8λŒ€ μœ„μƒμœΌλ‘œ λ§€ν•‘ pub fn ingest_raw_tensor(&mut self, raw_weights: &[f32]) { assert_eq!(raw_weights.len(), self.size * self.size); for (i, &w) in raw_weights.iter().enumerate() { self.ingested_weights[i] = Phase8::from_raw_weight(w); self.bedrock[i] = w * 0.1; // κ°€μ€‘μΉ˜μ˜ κΈ°μ € ν¬ν…μ…œ 흑수 } } /// μ„­μ·¨ν•œ κ°€μ€‘μΉ˜λ₯Ό 16개 μ½”μ–΄λ‘œ λ©€ν‹°μŠ€λ ˆλ“œ λΆ„ν•΄ 및 μ—λ„ˆμ§€ ν‰ν˜• 동화(Digestion) pub fn digest_step(&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_weights = &self.ingested_weights; let bedrock = &self.bedrock; let (next_weights, 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 = 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_sum = ( prev_weights[u].to_weight() + prev_weights[d].to_weight() + prev_weights[l].to_weight() + prev_weights[r].to_weight() ) * 0.25; let absorbed_field = neighbor_sum + bedrock[idx]; local_chunk.push(Phase8::from_raw_weight(absorbed_field)); local_energy += absorbed_field.abs(); } } (local_chunk, local_energy) })); } let mut combined = Vec::with_capacity(total); let mut energy_sum = 0.0f32; for h in handles { let (chunk, e) = h.join().unwrap(); combined.extend(chunk); energy_sum += e; } (combined, energy_sum) }); self.ingested_weights = next_weights; total_energy / (total as f32) } } fn main() { println!("============================================================"); println!(" πŸ₯© λŒ€κ·œλͺ¨ κ°€μ€‘μΉ˜ ν…μ„œ μ„­μ·¨(Ingestion) 및 μœ„μƒ μ†Œν™” μ—”μ§„"); println!("============================================================\n"); let grid_size = 1024; // 1,048,576 κ°€μ€‘μΉ˜ νŒŒλΌλ―Έν„° (1M ν…μ„œ) let total_params = grid_size * grid_size; let threads = 16; println!("πŸ“₯ [1단계] λŒ€κ·œλͺ¨ κ°€μ€‘μΉ˜ ν…μ„œ(1,048,576개 νŒŒλΌλ―Έν„°) μ€€λΉ„ 쀑..."); // 100만 개의 λΆ€λ™μ†Œμˆ˜μ  κ°€μ€‘μΉ˜ 데이터 생성 let raw_tensor: Vec = (0..total_params) .map(|i| ((i as f32 * 0.01).sin() * 2.0)) .collect(); let mut engine = WeightDigestionEngine::new(grid_size); println!("🍽️ [2단계] 100만 개 κ°€μ€‘μΉ˜λ₯Ό 8λŒ€ μœ„μƒ 격자둜 μ¦‰μ‹œ μ„­μ·¨(Ingest) μ™„λ£Œ\n"); let ingest_start = Instant::now(); engine.ingest_raw_tensor(&raw_tensor); let ingest_dur = ingest_start.elapsed().as_secs_f64() * 1000.0; println!(" └─ 100만 κ°€μ€‘μΉ˜ λ©”λͺ¨λ¦¬ 흑수 μ†Œμš” μ‹œκ°„: {:.2} ms\n", ingest_dur); println!("⚑ [3단계] 16개 μ½”μ–΄ λ™μ‹œ 가동: μ„­μ·¨λœ κ°€μ€‘μΉ˜ μ—λ„ˆμ§€ λΆ„ν•΄ 및 동화 쀑..."); let digest_start = Instant::now(); for tick in 1..=5 { let avg_e = engine.digest_step(threads); println!(" └─ [μ†Œν™” Tick {:02}] κ°€μ€‘μΉ˜ ν‰ν˜• μ—λ„ˆμ§€: {:.4}", tick, avg_e); } let digest_dur = digest_start.elapsed().as_secs_f64(); let total_digested = (total_params * 5) as f64; let digestion_rate = (total_digested / digest_dur) / 1e6; println!("\n============================================================"); println!(" πŸ“Š κ°€μ€‘μΉ˜ μ„­μ·¨ 및 동화 μ‹€μΈ‘ κ²°κ³Ό"); println!("============================================================"); println!(" πŸ₯© 총 μ„­μ·¨ νŒŒλΌλ―Έν„° 수 : {}개 (μ•½ 105만 개)", total_params); println!(" ⏱️ 5-Tick μ™„μ „ μ†Œν™” μ‹œκ°„ : {:.4} 초 ({:.2} ms)", digest_dur, digest_dur * 1000.0); println!(" ⚑ κ°€μ€‘μΉ˜ μ†Œν™” 처리율 : {:.2} MParam/sec (μ΄ˆλ‹Ή 1μ–΅ 개 이상)", digestion_rate); println!("============================================================"); }