File size: 3,891 Bytes
be99550 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 | // ๐ ๋๊ท๋ชจ 100๋ง ๋
ธ๋(1024x1024) ๋ณ๋ ฌ ๋ณต์ก๊ณ ์์ง (src/parallel_engine.rs)
use rayon::prelude::*;
use rand::Rng;
#[derive(Copy, Clone, Debug, PartialEq)]
#[repr(u8)]
pub enum PhaseState {
HyperInhibition = 0,
StandardInhibition = 1,
SubInhibition = 2,
NegQuiescent = 3,
PosQuiescent = 4,
SubExcitation = 5,
StandardExcitation = 6,
HyperExcitation = 7,
}
impl PhaseState {
#[inline(always)]
pub fn value(&self) -> f32 {
match self {
PhaseState::HyperInhibition => -2.0,
PhaseState::StandardInhibition => -1.0,
PhaseState::SubInhibition => -0.5,
PhaseState::NegQuiescent => -0.01,
PhaseState::PosQuiescent => 0.01,
PhaseState::SubExcitation => 0.5,
PhaseState::StandardExcitation => 1.0,
PhaseState::HyperExcitation => 2.0,
}
}
#[inline(always)]
pub fn from_energy(e: f32) -> Self {
if e <= -1.5 { PhaseState::HyperInhibition }
else if e <= -0.75 { PhaseState::StandardInhibition }
else if e <= -0.25 { PhaseState::SubInhibition }
else if e <= 0.0 { PhaseState::NegQuiescent }
else if e <= 0.25 { PhaseState::PosQuiescent }
else if e <= 0.75 { PhaseState::SubExcitation }
else if e <= 1.5 { PhaseState::StandardExcitation }
else { PhaseState::HyperExcitation }
}
}
pub struct LargeScaleEngine {
pub size: usize,
pub bedrock: Vec<f32>,
pub topsoil: Vec<PhaseState>,
}
impl LargeScaleEngine {
pub fn new(size: usize) -> Self {
let mut rng = rand::thread_rng();
let total_nodes = size * size;
let bedrock: Vec<f32> = (0..total_nodes).map(|_| rng.gen_range(-0.5..0.5)).collect();
let topsoil: Vec<PhaseState> = (0..total_nodes).map(|_| PhaseState::from_energy(rng.gen_range(-2.0..2.0))).collect();
LargeScaleEngine { size, bedrock, topsoil }
}
/// Rayon ๋ฉํฐ์ค๋ ๋ ๋ณ๋ ฌ ์ํ ์ ์ด (100๋ง ๋
ธ๋ ๋ถํ ์ฒ๋ฆฌ)
pub fn step_parallel(&mut self) -> f32 {
let size = self.size;
let prev_topsoil = &self.topsoil;
let bedrock = &self.bedrock;
// ์ฒญํฌ(Row) ๋จ์ ๋ฉํฐ์ค๋ ๋ ๋ณ๋ ฌ ๊ฐฑ์
let (next_topsoil, total_energy): (Vec<PhaseState>, f32) = (0..size)
.into_par_iter()
.map(|y| {
let mut row_states = Vec::with_capacity(size);
let mut row_energy = 0.0f32;
let s = size as i32;
for x in 0..size {
let idx = y * size + x;
let up_idx = ((y as i32 - 1 + s) % s * s + x as i32) as usize;
let down_idx = ((y as i32 + 1) % s * s + x as i32) as usize;
let left_idx = (y as i32 * s + (x as i32 - 1 + s) % s) as usize;
let right_idx = (y as i32 * s + (x as i32 + 1) % s) as usize;
let neighbor_e = (
prev_topsoil[up_idx].value() +
prev_topsoil[down_idx].value() +
prev_topsoil[left_idx].value() +
prev_topsoil[right_idx].value()
) * 0.25;
let local_field = neighbor_e + bedrock[idx];
row_states.push(PhaseState::from_energy(local_field));
row_energy += local_field.abs();
}
(row_states, row_energy)
})
.reduce(
|| (Vec::with_capacity(size * size), 0.0f32),
|mut acc, (row_states, row_e)| {
acc.0.extend(row_states);
acc.1 += row_e;
acc
},
);
self.topsoil = next_topsoil;
total_energy / (size * size) as f32
}
}
|