diff --git a/Cargo.toml b/Cargo.toml index df00865..6f02c8c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,8 +12,6 @@ itertools = "0.10" rand = "0.8.3" rand_distr = "0.4" rayon = "1.5" -arrayfire = {git = "https://github.com/arrayfire/arrayfire-rust.git"} -#arrayfire = "3.8.0" [dev-dependencies] criterion = "0.3" diff --git a/src/main.rs b/src/main.rs index 22321db..2e5bc30 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,17 +2,8 @@ use chrono::{DateTime, Utc}; use indicatif::{ProgressBar, ProgressStyle}; use physarum::model; use rand::Rng; -use arrayfire as af; fn main() { - let gpu_compute: bool = false; - if gpu_compute { - backend_man(); - // af::set_backend(af::Backend::CPU); - af::set_device(0); - af::info(); - } - // let n_iterations = 16384; let n_iterations = 1024; // let n_iterations = 100; @@ -38,43 +29,11 @@ fn main() { let mut model = model::Model::new(width, height, n_particles, n_populations, diffusivity); model.print_configurations(); - if gpu_compute { - model.run_cl(n_iterations); - } else { - model.run(n_iterations); - } + model.run(n_iterations); println!("Rendering all saved image data...."); model.render_all_imgdata(); model.flush_image_data(); println!("Done!"); -} - - -fn backend_man() { - let available = af::get_available_backends(); - - if available.contains(&af::Backend::CUDA) { - println!("Evaluating CUDA Backend..."); - af::set_backend(af::Backend::CUDA); - println!("There are {} CUDA compute devices", af::device_count()); - return; - } - - /* - if available.contains(&af::Backend::OPENCL) { - println!("Evaluating OpenCL Backend..."); - af::set_backend(af::Backend::OPENCL); - println!("There are {} OpenCL compute devices", af::device_count()); - return; - } - */ - - if available.contains(&af::Backend::CPU) { - println!("Evaluating CPU Backend..."); - af::set_backend(af::Backend::CPU); - println!("There are {} CPU compute devices", af::device_count()); - return; - } -} +} \ No newline at end of file diff --git a/src/model.rs b/src/model.rs index efed3bb..022888e 100644 --- a/src/model.rs +++ b/src/model.rs @@ -12,7 +12,6 @@ use std::f32::consts::TAU; use std::time::{Duration, Instant}; use rayon::iter::{ParallelIterator, IntoParallelIterator}; use indicatif::{ParallelProgressIterator, ProgressBar, ProgressStyle}; -use arrayfire as af; use std::path::Path; /// A single Physarum agent. The x and y positions are continuous, hence we use floating point @@ -250,155 +249,6 @@ impl Model { pb.finish(); } - // Currently VERY poorly implemented (allocates memory each iteration) - // I need to learn more about gpu compute to tackle this one - pub fn run_cl(&mut self, steps: usize) { - let pb = ProgressBar::new(steps as u64); - pb.set_style( - ProgressStyle::default_bar() - .template( - "{spinner:.green} [{elapsed_precise}] [{bar:40.cyan/blue}] {pos}/{len} ({eta} {percent}%, {per_sec})", - ) - .progress_chars("#>-"), - ); - - // Combine grids - let grids = &mut self.grids; - combine(grids, &self.attraction_table); - - let agents_list = &*self.agents.clone(); - - - let agent_num: usize = agents_list.len() as usize; - let dims = af::Dim4::new(&[agent_num as u64, 1, 1, 1]); - - - let mut sensor_distance_list: Vec = Vec::new(); - let mut sensor_angle_list: Vec = Vec::new(); - let mut rotation_angle_list: Vec = Vec::new(); - let mut step_distance_list: Vec = Vec::new(); - - // Need to fix, super slow - for agent in &*self.agents.clone() { - let PopulationConfig { - sensor_distance, - sensor_angle, - rotation_angle, - step_distance, - .. - } = &grids.clone()[agent.population_id].config; - sensor_distance_list.push(*sensor_distance); - sensor_angle_list.push(*sensor_angle); - rotation_angle_list.push(*rotation_angle); - step_distance_list.push(*step_distance); - } - - let sensor_distance = af::Array::new(&sensor_distance_list, dims); - let sensor_angle = af::Array::new(&sensor_angle_list, dims); - - - - let mut agent_angles_list: Vec = Vec::new(); - let mut agent_x_list: Vec = Vec::new(); - let mut agent_y_list: Vec = Vec::new(); - - for i in 0..steps { - let grids = &mut self.grids; - combine(grids, &self.attraction_table); - - println!("Starting tick for all agents..."); - let agents_tick_time = Instant::now(); - agent_angles_list = agents_list.iter().map(|agent| agent.angle).collect(); - agent_x_list = agents_list.iter().map(|agent| agent.x).collect(); - agent_y_list = agents_list.iter().map(|agent| agent.y).collect(); - - - let agent_x = af::Array::new(&agent_x_list, dims); - let agent_y = af::Array::new(&agent_y_list, dims); - let agent_angles = af::Array::new(&agent_angles_list, dims); - - let cos_angles = af::cos(&agent_angles); - let sin_angles = af::sin(&agent_angles); - - let cos_angle_dis = af::mul(&cos_angles, &sensor_distance, false); - let sin_angle_dis = af::mul(&sin_angles, &sensor_distance, false); - - let xc_array = &af::add(&agent_x, &cos_angle_dis, false); - let yc_array = &af::add(&agent_y, &sin_angle_dis, false); - - let xc = Self::to_vec(xc_array); - let yc = Self::to_vec(yc_array); - - let agent_add_sens = af::add(&agent_angles, &sensor_angle, false); - let agent_sub_sens = af::sub(&agent_angles, &sensor_angle, false); - - let agent_add_sens_mul = af::mul(&agent_add_sens, &sensor_distance, false); - let agent_sub_sens_mul = af::mul(&agent_sub_sens, &sensor_distance, false); - - let xl_array = &af::add(&agent_x, &af::sin(&agent_sub_sens_mul), false); - let yl_array = &af::add(&agent_y, &af::sin(&agent_sub_sens_mul), false); - let xr_array = &af::add(&agent_x, &af::sin(&agent_add_sens_mul), false); - let yr_array = &af::add(&agent_y, &af::sin(&agent_add_sens_mul), false); - - let xl = Self::to_vec(xl_array); - let yl = Self::to_vec(yl_array); - let xr = Self::to_vec(xr_array); - let yr = Self::to_vec(yr_array); - - - self.agents.par_iter_mut().for_each(|agent| { - let i: usize = agent.i; - - let rotation_angle = rotation_angle_list[i]; - let step_distance = rotation_angle_list[i]; - - let xc = xc[i]; - let xl = xl[i]; - let xr = xr[i]; - let yc = yc[i]; - let yl = yl[i]; - let yr = yr[i]; - - let grid = &grids[agent.population_id]; - let (width, height) = (grid.width, grid.height); - - let trail_c = grid.get_buf(xc, yc); - let trail_l = grid.get_buf(xl, yl); - let trail_r = grid.get_buf(xr, yr); - - let mut rng = rand::thread_rng(); - let direction = Model::pick_direction(trail_c, trail_l, trail_r, &mut rng); - agent.rotate_and_move(direction, rotation_angle, step_distance, width, height); - }); - - let agents_tick_elapsed = agents_tick_time.elapsed().as_millis(); - let ms_per_agent: f64 = (agents_tick_elapsed as f64) / (self.agents.len() as f64); - println!("Finished tick for all agents. took {}ms\nTime per agent: {}ms\n", agents_tick_time.elapsed().as_millis(), ms_per_agent); - - // Deposit - for agent in self.agents.iter() { - self.grids[agent.population_id].deposit(agent.x, agent.y); - } - - // Diffuse + Decay - let diffusivity = self.diffusivity; - self.grids.par_iter_mut().for_each(|grid| { - grid.diffuse(diffusivity); - }); - - self.save_image_data(); - self.iteration += 1; - pb.set_position(i as u64); - } - pb.finish(); - } - - fn to_vec(array: &af::Array) -> Vec { - let mut vec = vec!(T::default();array.elements()); - array.host(&mut vec); - return vec; - } - fn save_image_data(&mut self) { let grids = self.grids.clone(); self.img_data_vec.push(ImgData::new(grids, self.palette, self.iteration));