Added shared_unsafe type and provided examples

This commit is contained in:
a 2021-05-01 18:59:14 -04:00 committed by Yiyao Yu
parent 8227ae5c65
commit 1f144cb1af
2 changed files with 152 additions and 9 deletions

View File

@ -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<Vec<f64>> {
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::<f64>() - 0.5) * 255.0);
}
ret.push(row);
}
ret
}
fn gen_empty(nsize: usize) -> Vec<Vec<f64>> {
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<String> = env::args().collect();
if args.len() != 2 {
eprintln!("Usage: {} <msize>", args[0]);
return;
}
let nsize = max(args[1].parse::<usize>().expect("Usage: matrix_mul <msize>"), 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);
}

View File

@ -2,6 +2,7 @@ pub mod threadpool;
mod sysinfo; mod sysinfo;
use std::ops::{DerefMut, Deref};
use std::sync::{Arc, RwLock, RwLockReadGuard, RwLockWriteGuard}; use std::sync::{Arc, RwLock, RwLockReadGuard, RwLockWriteGuard};
pub use threadpool::{as_static_job, Job, ThreadPoolManager}; pub use threadpool::{as_static_job, Job, ThreadPoolManager};
@ -12,9 +13,9 @@ pub struct Capture<T> {
impl<T> Capture<T> { impl<T> Capture<T> {
pub fn new(inner: T) -> Capture<T> { pub fn new(inner: T) -> Capture<T> {
return Capture { Capture {
value: Arc::new(RwLock::new(inner)), value: Arc::new(RwLock::new(inner)),
}; }
} }
pub fn clone(&self) -> Capture<T> { pub fn clone(&self) -> Capture<T> {
@ -39,6 +40,44 @@ impl<T> Capture<T> {
} }
} }
pub struct UnsafePtr<T> {
pub value: *mut T,
}
impl<T> UnsafePtr<T> {
pub fn new(obj: &mut T) -> UnsafePtr<T> {
UnsafePtr {
value: obj as *mut T,
}
}
}
impl<T> Copy for UnsafePtr<T> {}
impl<T> Clone for UnsafePtr<T> {
fn clone(&self) -> Self {
UnsafePtr { value: self.value }
}
}
impl<T> Deref for UnsafePtr<T> {
type Target = T;
fn deref(&self) -> &T {
unsafe { self.value.as_ref().unwrap() }
}
}
impl<T> DerefMut for UnsafePtr<T> {
fn deref_mut(&mut self) -> &mut Self::Target {
unsafe { self.value.as_mut().unwrap() }
}
}
unsafe impl<T> Send for UnsafePtr<T> {}
unsafe impl<T> Sync for UnsafePtr<T> {}
#[macro_export] #[macro_export]
macro_rules! critical { macro_rules! critical {
(read $($r:ident)+; readwrite $($w:ident)+; $($ops:tt)+) => { (read $($r:ident)+; readwrite $($w:ident)+; $($ops:tt)+) => {
@ -85,22 +124,25 @@ macro_rules! __internal_par_for {
blocksize($size:expr), blocksize($size:expr),
shared_mut($($shared_mut:ident)*), shared_mut($($shared_mut:ident)*),
shared($($shared:ident)*), shared($($shared:ident)*),
shared_unsafe($($shared_unsafe:ident)*),
private($($private:ident)*), private($($private:ident)*),
reduction(), reduction(),
$blk:block) => { $blk:block) => {
let mut __rmp_tasks = Vec::new();
$(let $shared_mut = rustmp::Capture::new($shared_mut);)* $(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_mtx = rustmp::ThreadPoolManager::get_instance_guard();
let __rmp_tpm = __rmp_tpm_mtx.lock().unwrap(); let __rmp_tpm = __rmp_tpm_mtx.lock().unwrap();
let __rmp_iters = __rmp_tpm.split_iterators($iter, $size); let __rmp_iters = __rmp_tpm.split_iterators($iter, $size);
for iter in __rmp_iters { for iter in __rmp_iters {
$(let $shared_mut = $shared_mut.clone();)* $(let $shared_mut = $shared_mut.clone();)*
$(let $shared = $shared.clone();)* $(let $shared = $shared.clone();)*
// $(let $private = $private.clone();)* $(let $private = $private.clone();)*
__rmp_tasks.push(rustmp::as_static_job(move || { __rmp_tasks.push(rustmp::as_static_job(move || {
$(let mut $private = $private.clone();)* $(let mut $private = $private.clone();)*
$(let mut $shared_unsafe = $shared_unsafe.clone();)*
for &$name in &iter for &$name in &iter
$blk $blk
})); }));
@ -109,19 +151,22 @@ macro_rules! __internal_par_for {
} }
$(let $shared_mut = $shared_mut.unwrap();)* $(let $shared_mut = $shared_mut.unwrap();)*
}; };
// with reduction // with reduction
(var_name($name:ident), (var_name($name:ident),
iterator($iter:expr), iterator($iter:expr),
blocksize($size:expr), blocksize($size:expr),
shared_mut($($shared_mut:ident)*), shared_mut($($shared_mut:ident)*),
shared($($shared:ident)*), shared($($shared:ident)*),
shared_unsafe($($shared_unsafe:ident)*),
private($($private:ident)*), private($($private:ident)*),
reduction($($red_name:ident, $red_op:tt)+), reduction($($red_name:ident, $red_op:tt)+),
$blk:block) => { $blk:block) => {
let mut __rmp_tasks = Vec::new();
$(let $shared_mut = rustmp::Capture::new($shared_mut);)* $(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_mtx = rustmp::ThreadPoolManager::get_instance_guard();
let __rmp_tpm = __rmp_tpm_mtx.lock().unwrap(); let __rmp_tpm = __rmp_tpm_mtx.lock().unwrap();
let __rmp_iters = __rmp_tpm.split_iterators($iter, $size); let __rmp_iters = __rmp_tpm.split_iterators($iter, $size);
@ -131,11 +176,12 @@ macro_rules! __internal_par_for {
for iter in __rmp_iters { for iter in __rmp_iters {
$(let $shared_mut = $shared_mut.clone();)* $(let $shared_mut = $shared_mut.clone();)*
$(let $shared = $shared.clone();)* $(let $shared = $shared.clone();)*
// $(let $private = $private.clone();)* $(let $private = $private.clone();)*
let __rmp_red_vals = __rmp_red_vals.clone(); let __rmp_red_vals = __rmp_red_vals.clone();
$(let $red_name = $red_name.clone();)* $(let $red_name = $red_name.clone();)*
__rmp_tasks.push(rustmp::as_static_job(move || { __rmp_tasks.push(rustmp::as_static_job(move || {
$(let mut $private = $private.clone();)* $(let mut $private = $private.clone();)*
$(let mut $shared_unsafe = $shared_unsafe.clone();)*
$(let mut $red_name = $red_name.clone();)* $(let mut $red_name = $red_name.clone();)*
for &$name in &iter for &$name in &iter
$blk $blk
@ -147,17 +193,21 @@ macro_rules! __internal_par_for {
__rmp_tpm.exec(__rmp_tasks); __rmp_tpm.exec(__rmp_tasks);
let mut __rmp_temp = __rmp_red_vals.read(); let mut __rmp_temp = __rmp_red_vals.read();
let mut __rmp_counter = 0; 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;)* __rmp_counter += 1;)*
} }
$(let $shared_mut = $shared_mut.unwrap();)* $(let $shared_mut = $shared_mut.unwrap();)*
}; };
// Parse blocksize // Parse blocksize
(var_name($name:ident), (var_name($name:ident),
iterator($iter:expr), iterator($iter:expr),
blocksize($size:expr), blocksize($size:expr),
shared_mut($($shared_mut:ident)*), shared_mut($($shared_mut:ident)*),
shared($($shared:ident)*), shared($($shared:ident)*),
shared_unsafe($($shared_unsafe:ident)*),
private($($private:ident)*), private($($private:ident)*),
reduction($($red_name:ident, $red_op:tt)*), reduction($($red_name:ident, $red_op:tt)*),
blocksize $new_size:expr, blocksize $new_size:expr,
@ -168,16 +218,19 @@ macro_rules! __internal_par_for {
blocksize($new_size), blocksize($new_size),
shared_mut($($shared_mut)*), shared_mut($($shared_mut)*),
shared($($shared)*), shared($($shared)*),
shared_unsafe($($shared_unsafe)*),
private($($private)*), private($($private)*),
reduction($($red_name, $red_op)*), reduction($($red_name, $red_op)*),
$($rem)*) $($rem)*)
}; };
// Parse shared_mut // Parse shared_mut
(var_name($name:ident), (var_name($name:ident),
iterator($iter:expr), iterator($iter:expr),
blocksize($size:expr), blocksize($size:expr),
shared_mut($($shared_mut:ident)*), shared_mut($($shared_mut:ident)*),
shared($($shared:ident)*), shared($($shared:ident)*),
shared_unsafe($($shared_unsafe:ident)*),
private($($private:ident)*), private($($private:ident)*),
reduction($($red_name:ident, $red_op:tt)*), reduction($($red_name:ident, $red_op:tt)*),
shared_mut $($new_shared_mut:ident)*, shared_mut $($new_shared_mut:ident)*,
@ -188,16 +241,19 @@ macro_rules! __internal_par_for {
blocksize($size), blocksize($size),
shared_mut($($new_shared_mut)*), shared_mut($($new_shared_mut)*),
shared($($shared)*), shared($($shared)*),
shared_unsafe($($shared_unsafe)*),
private($($private)*), private($($private)*),
reduction($($red_name, $red_op)*), reduction($($red_name, $red_op)*),
$($rem)*) $($rem)*)
}; };
// Parse shared // Parse shared
(var_name($name:ident), (var_name($name:ident),
iterator($iter:expr), iterator($iter:expr),
blocksize($size:expr), blocksize($size:expr),
shared_mut($($shared_mut:ident)*), shared_mut($($shared_mut:ident)*),
shared($($shared:ident)*), shared($($shared:ident)*),
shared_unsafe($($shared_unsafe:ident)*),
private($($private:ident)*), private($($private:ident)*),
reduction($($red_name:ident, $red_op:tt)*), reduction($($red_name:ident, $red_op:tt)*),
shared $($new_name:ident)*, shared $($new_name:ident)*,
@ -208,16 +264,42 @@ macro_rules! __internal_par_for {
blocksize($size), blocksize($size),
shared_mut($($shared_mut)*), shared_mut($($shared_mut)*),
shared($($new_name)*), shared($($new_name)*),
shared_unsafe($($shared_unsafe)*),
private($($private)*), private($($private)*),
reduction($($red_name, $red_op)*), reduction($($red_name, $red_op)*),
$($rem)*) $($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 // Parse private
(var_name($name:ident), (var_name($name:ident),
iterator($iter:expr), iterator($iter:expr),
blocksize($size:expr), blocksize($size:expr),
shared_mut($($shared_mut:ident)*), shared_mut($($shared_mut:ident)*),
shared($($shared:ident)*), shared($($shared:ident)*),
shared_unsafe($($shared_unsafe:ident)*),
private($($private:ident)*), private($($private:ident)*),
reduction($($red_name:ident, $red_op:tt)*), reduction($($red_name:ident, $red_op:tt)*),
private $($new_private:ident)*, private $($new_private:ident)*,
@ -228,16 +310,19 @@ macro_rules! __internal_par_for {
blocksize($size), blocksize($size),
shared_mut($($shared_mut)*), shared_mut($($shared_mut)*),
shared($($shared)*), shared($($shared)*),
shared_unsafe($($shared_unsafe)*),
private($($new_private)*), private($($new_private)*),
reduction($($red_name, $red_op)*), reduction($($red_name, $red_op)*),
$($rem)*) $($rem)*)
}; };
// Parse reduction // Parse reduction
(var_name($name:ident), (var_name($name:ident),
iterator($iter:expr), iterator($iter:expr),
blocksize($size:expr), blocksize($size:expr),
shared_mut($($shared_mut:ident)*), shared_mut($($shared_mut:ident)*),
shared($($shared:ident)*), shared($($shared:ident)*),
shared_unsafe($($shared_unsafe:ident)*),
private($($private:ident)*), private($($private:ident)*),
reduction($($red_name:ident, $red_op:tt)*), reduction($($red_name:ident, $red_op:tt)*),
reduction $($new_name:ident#$new_op:tt);*, reduction $($new_name:ident#$new_op:tt);*,
@ -248,10 +333,12 @@ macro_rules! __internal_par_for {
blocksize($size), blocksize($size),
shared_mut($($shared_mut)*), shared_mut($($shared_mut)*),
shared($($shared)*), shared($($shared)*),
shared_unsafe($($shared_unsafe)*),
private($($private)*), private($($private)*),
reduction($($new_name, $new_op)*), reduction($($new_name, $new_op)*),
$($rem)*) $($rem)*)
}; };
} }
/// "parallel for" wrapper /// "parallel for" wrapper
@ -267,6 +354,7 @@ macro_rules! par_for {
blocksize(1), blocksize(1),
shared_mut(), shared_mut(),
shared(), shared(),
shared_unsafe(),
private(), private(),
reduction(), reduction(),
$($rem)*) $($rem)*)