From 1f144cb1af8732009639a9a3a6ece3fa38d1da9c Mon Sep 17 00:00:00 2001 From: a Date: Sat, 1 May 2021 18:59:14 -0400 Subject: [PATCH] Added shared_unsafe type and provided examples --- src/bin/rmpunsafe_matmul.rs | 55 +++++++++++++++++++ src/lib.rs | 106 +++++++++++++++++++++++++++++++++--- 2 files changed, 152 insertions(+), 9 deletions(-) create mode 100644 src/bin/rmpunsafe_matmul.rs diff --git a/src/bin/rmpunsafe_matmul.rs b/src/bin/rmpunsafe_matmul.rs new file mode 100644 index 0000000..b6ee153 --- /dev/null +++ b/src/bin/rmpunsafe_matmul.rs @@ -0,0 +1,55 @@ +use std::env; +use std::cmp::max; +use rand::random; +use std::time::Instant; + +use rustmp::par_for; + +fn gen_matrix(nsize: usize) -> Vec> { + let mut ret = Vec::with_capacity(nsize); + for _ in 0..nsize { + let mut row = Vec::with_capacity(nsize); + for _ in 0..nsize { + row.push((random::() - 0.5) * 255.0); + } + ret.push(row); + } + ret +} + +fn gen_empty(nsize: usize) -> Vec> { + let mut ret = Vec::with_capacity(nsize); + let mut row = Vec::with_capacity(nsize); + for _ in 0..nsize { + row.push(0 as f64); + } + for _ in 0..nsize { + ret.push(row.clone()); + } + ret +} + +fn main() { + let args: Vec = env::args().collect(); + if args.len() != 2 { + eprintln!("Usage: {} ", args[0]); + return; + } + let nsize = max(args[1].parse::().expect("Usage: matrix_mul "), 1); + let matrix = gen_matrix(nsize); + let mut result = gen_empty(nsize); + let timer = Instant::now(); + par_for! { + for i in 0..nsize, shared_unsafe result, shared matrix, { + for j in 0..nsize { + let mut sum = 0.0; + for k in 0..nsize { + sum += matrix[i][k] * matrix[k][j]; + } + result[i][j] = sum; + } + } + } + let interval = timer.elapsed(); + println!("Elapsed time: {:?}", interval); +} diff --git a/src/lib.rs b/src/lib.rs index c52fc83..8ffb8ff 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,6 +2,7 @@ pub mod threadpool; mod sysinfo; +use std::ops::{DerefMut, Deref}; use std::sync::{Arc, RwLock, RwLockReadGuard, RwLockWriteGuard}; pub use threadpool::{as_static_job, Job, ThreadPoolManager}; @@ -12,9 +13,9 @@ pub struct Capture { impl Capture { pub fn new(inner: T) -> Capture { - return Capture { + Capture { value: Arc::new(RwLock::new(inner)), - }; + } } pub fn clone(&self) -> Capture { @@ -39,6 +40,44 @@ impl Capture { } } +pub struct UnsafePtr { + pub value: *mut T, +} + +impl UnsafePtr { + pub fn new(obj: &mut T) -> UnsafePtr { + UnsafePtr { + value: obj as *mut T, + } + } +} + +impl Copy for UnsafePtr {} + +impl Clone for UnsafePtr { + fn clone(&self) -> Self { +UnsafePtr { value: self.value } + } +} + +impl Deref for UnsafePtr { + type Target = T; + + fn deref(&self) -> &T { + unsafe { self.value.as_ref().unwrap() } + } +} + +impl DerefMut for UnsafePtr { + fn deref_mut(&mut self) -> &mut Self::Target { +unsafe { self.value.as_mut().unwrap() } + } +} + +unsafe impl Send for UnsafePtr {} +unsafe impl Sync for UnsafePtr {} + + #[macro_export] macro_rules! critical { (read $($r:ident)+; readwrite $($w:ident)+; $($ops:tt)+) => { @@ -85,22 +124,25 @@ macro_rules! __internal_par_for { blocksize($size:expr), shared_mut($($shared_mut:ident)*), shared($($shared:ident)*), + shared_unsafe($($shared_unsafe:ident)*), private($($private:ident)*), reduction(), $blk:block) => { - let mut __rmp_tasks = Vec::new(); $(let $shared_mut = rustmp::Capture::new($shared_mut);)* - $(let $shared = std::sync::Arc::new($shared.clone());)* { + let mut __rmp_tasks = Vec::new(); + $(let $shared = std::sync::Arc::new($shared.clone());)* + $(let $shared_unsafe = rustmp::UnsafePtr::new(&mut $shared_unsafe);)* let __rmp_tpm_mtx = rustmp::ThreadPoolManager::get_instance_guard(); let __rmp_tpm = __rmp_tpm_mtx.lock().unwrap(); let __rmp_iters = __rmp_tpm.split_iterators($iter, $size); for iter in __rmp_iters { $(let $shared_mut = $shared_mut.clone();)* $(let $shared = $shared.clone();)* - // $(let $private = $private.clone();)* + $(let $private = $private.clone();)* __rmp_tasks.push(rustmp::as_static_job(move || { $(let mut $private = $private.clone();)* + $(let mut $shared_unsafe = $shared_unsafe.clone();)* for &$name in &iter $blk })); @@ -109,19 +151,22 @@ macro_rules! __internal_par_for { } $(let $shared_mut = $shared_mut.unwrap();)* }; + // with reduction (var_name($name:ident), iterator($iter:expr), blocksize($size:expr), shared_mut($($shared_mut:ident)*), shared($($shared:ident)*), + shared_unsafe($($shared_unsafe:ident)*), private($($private:ident)*), reduction($($red_name:ident, $red_op:tt)+), $blk:block) => { - let mut __rmp_tasks = Vec::new(); $(let $shared_mut = rustmp::Capture::new($shared_mut);)* - $(let $shared = std::sync::Arc::new($shared.clone());)* { + let mut __rmp_tasks = Vec::new(); + $(let $shared = std::sync::Arc::new($shared.clone());)* + $(let $shared_unsafe = rustmp::UnsafePtr::new(&mut $shared_unsafe);)* let __rmp_tpm_mtx = rustmp::ThreadPoolManager::get_instance_guard(); let __rmp_tpm = __rmp_tpm_mtx.lock().unwrap(); let __rmp_iters = __rmp_tpm.split_iterators($iter, $size); @@ -131,11 +176,12 @@ macro_rules! __internal_par_for { for iter in __rmp_iters { $(let $shared_mut = $shared_mut.clone();)* $(let $shared = $shared.clone();)* - // $(let $private = $private.clone();)* + $(let $private = $private.clone();)* let __rmp_red_vals = __rmp_red_vals.clone(); $(let $red_name = $red_name.clone();)* __rmp_tasks.push(rustmp::as_static_job(move || { $(let mut $private = $private.clone();)* + $(let mut $shared_unsafe = $shared_unsafe.clone();)* $(let mut $red_name = $red_name.clone();)* for &$name in &iter $blk @@ -147,17 +193,21 @@ macro_rules! __internal_par_for { __rmp_tpm.exec(__rmp_tasks); let mut __rmp_temp = __rmp_red_vals.read(); let mut __rmp_counter = 0; - $($red_name = __rmp_temp[__rmp_counter].iter().fold($red_name, rustmp::__reduction_operation!($red_op)); + $($red_name = __rmp_temp[__rmp_counter] + .iter() + .fold($red_name, rustmp::__reduction_operation!($red_op)); __rmp_counter += 1;)* } $(let $shared_mut = $shared_mut.unwrap();)* }; + // Parse blocksize (var_name($name:ident), iterator($iter:expr), blocksize($size:expr), shared_mut($($shared_mut:ident)*), shared($($shared:ident)*), + shared_unsafe($($shared_unsafe:ident)*), private($($private:ident)*), reduction($($red_name:ident, $red_op:tt)*), blocksize $new_size:expr, @@ -168,16 +218,19 @@ macro_rules! __internal_par_for { blocksize($new_size), shared_mut($($shared_mut)*), shared($($shared)*), + shared_unsafe($($shared_unsafe)*), private($($private)*), reduction($($red_name, $red_op)*), $($rem)*) }; + // Parse shared_mut (var_name($name:ident), iterator($iter:expr), blocksize($size:expr), shared_mut($($shared_mut:ident)*), shared($($shared:ident)*), + shared_unsafe($($shared_unsafe:ident)*), private($($private:ident)*), reduction($($red_name:ident, $red_op:tt)*), shared_mut $($new_shared_mut:ident)*, @@ -188,16 +241,19 @@ macro_rules! __internal_par_for { blocksize($size), shared_mut($($new_shared_mut)*), shared($($shared)*), + shared_unsafe($($shared_unsafe)*), private($($private)*), reduction($($red_name, $red_op)*), $($rem)*) }; + // Parse shared (var_name($name:ident), iterator($iter:expr), blocksize($size:expr), shared_mut($($shared_mut:ident)*), shared($($shared:ident)*), + shared_unsafe($($shared_unsafe:ident)*), private($($private:ident)*), reduction($($red_name:ident, $red_op:tt)*), shared $($new_name:ident)*, @@ -208,16 +264,42 @@ macro_rules! __internal_par_for { blocksize($size), shared_mut($($shared_mut)*), shared($($new_name)*), + shared_unsafe($($shared_unsafe)*), private($($private)*), reduction($($red_name, $red_op)*), $($rem)*) }; + + // Parse shared_unsafe + (var_name($name:ident), + iterator($iter:expr), + blocksize($size:expr), + shared_mut($($shared_mut:ident)*), + shared($($shared:ident)*), + shared_unsafe($($shared_unsafe:ident)*), + private($($private:ident)*), + reduction($($red_name:ident, $red_op:tt)*), + shared_unsafe $($new_shared_unsafe:ident)*, + $($rem:tt)+) => { + rustmp::__internal_par_for!( + var_name($name), + iterator($iter), + blocksize($size), + shared_mut($($shared_mut)*), + shared($($shared)*), + shared_unsafe($($new_shared_unsafe)*), + private($($private)*), + reduction($($red_name, $red_op)*), + $($rem)*) + }; + // Parse private (var_name($name:ident), iterator($iter:expr), blocksize($size:expr), shared_mut($($shared_mut:ident)*), shared($($shared:ident)*), + shared_unsafe($($shared_unsafe:ident)*), private($($private:ident)*), reduction($($red_name:ident, $red_op:tt)*), private $($new_private:ident)*, @@ -228,16 +310,19 @@ macro_rules! __internal_par_for { blocksize($size), shared_mut($($shared_mut)*), shared($($shared)*), + shared_unsafe($($shared_unsafe)*), private($($new_private)*), reduction($($red_name, $red_op)*), $($rem)*) }; + // Parse reduction (var_name($name:ident), iterator($iter:expr), blocksize($size:expr), shared_mut($($shared_mut:ident)*), shared($($shared:ident)*), + shared_unsafe($($shared_unsafe:ident)*), private($($private:ident)*), reduction($($red_name:ident, $red_op:tt)*), reduction $($new_name:ident#$new_op:tt);*, @@ -248,10 +333,12 @@ macro_rules! __internal_par_for { blocksize($size), shared_mut($($shared_mut)*), shared($($shared)*), + shared_unsafe($($shared_unsafe)*), private($($private)*), reduction($($new_name, $new_op)*), $($rem)*) }; + } /// "parallel for" wrapper @@ -267,6 +354,7 @@ macro_rules! par_for { blocksize(1), shared_mut(), shared(), + shared_unsafe(), private(), reduction(), $($rem)*)