Skip to content

Commit

Permalink
make user operations (and libffi) an optional default feature/dependency
Browse files Browse the repository at this point in the history
  • Loading branch information
bsteinb committed Feb 7, 2018
1 parent 9551dd7 commit ca8e6d7
Show file tree
Hide file tree
Showing 5 changed files with 72 additions and 31 deletions.
7 changes: 6 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,14 @@ keywords = [ "message-passing", "parallel" ]
license = "MIT OR Apache-2.0"
build = "build.rs"

[features]
default = ["user-operations"]

user-operations = ["libffi"]

[dependencies]
conv = "0.3"
libffi = "0.6.0"
libffi = { version = "0.6.0", optional = true }

[build-dependencies]
gcc = "0.3"
Expand Down
41 changes: 26 additions & 15 deletions examples/immediate_reduce.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,31 @@ extern crate mpi;

use mpi::traits::*;
use mpi::topology::Rank;
use mpi::collective::{SystemOperation, UserOperation};
use mpi::collective::SystemOperation;
#[cfg(feature = "user-operations")]
use mpi::collective::UserOperation;

#[cfg(feature = "user-operations")]
fn test_user_operations<C: Communicator>(comm: C) {
let op = UserOperation::commutative(|x, y| {
let x: &[Rank] = x.downcast().unwrap();
let y: &mut [Rank] = y.downcast().unwrap();
for (&x_i, y_i) in x.iter().zip(y) {
*y_i += x_i;
}
});
let rank = comm.rank();
let size = comm.size();
let mut c = 0;
mpi::request::scope(|scope| {
comm.immediate_all_reduce_into(scope, &rank, &mut c, &op)
.wait();
});
assert_eq!(c, size * (size - 1) / 2);
}

#[cfg(not(feature = "user-operations"))]
fn test_user_operations<C: Communicator>(_: C) {}

fn main() {
let universe = mpi::initialize().unwrap();
Expand Down Expand Up @@ -49,18 +73,5 @@ fn main() {
});
assert_eq!(b, rank.pow(size as u32));

let op = UserOperation::commutative(|x, y| {
let x: &[Rank] = x.downcast().unwrap();
let y: &mut [Rank] = y.downcast().unwrap();
for (&x_i, y_i) in x.iter().zip(y) {
*y_i += x_i;
}
});
let mut c = 0;
mpi::request::scope(|scope| {
world
.immediate_all_reduce_into(scope, &rank, &mut c, &op)
.wait();
});
assert_eq!(c, size * (size - 1) / 2);
test_user_operations(universe.world());
}
40 changes: 26 additions & 14 deletions examples/reduce.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,31 @@ extern crate mpi;

use mpi::traits::*;
use mpi::topology::Rank;
use mpi::collective::{self, SystemOperation, UserOperation};
use mpi::collective::{self, SystemOperation};
#[cfg(feature = "user-operations")]
use mpi::collective::UserOperation;

#[cfg(feature = "user-operations")]
fn test_user_operations<C: Communicator>(comm: C) {
let rank = comm.rank();
let size = comm.size();
let mut h = 0;
comm.all_reduce_into(
&(rank + 1),
&mut h,
&UserOperation::commutative(|x, y| {
let x: &[Rank] = x.downcast().unwrap();
let y: &mut [Rank] = y.downcast().unwrap();
for (&x_i, y_i) in x.iter().zip(y) {
*y_i += x_i;
}
}),
);
assert_eq!(h, size * (size + 1) / 2);
}

#[cfg(not(feature = "user-operations"))]
fn test_user_operations<C: Communicator>(_: C) {}

fn main() {
let universe = mpi::initialize().unwrap();
Expand Down Expand Up @@ -51,17 +75,5 @@ fn main() {
world.reduce_scatter_block_into(&f[..], &mut g, SystemOperation::product());
assert_eq!(g, rank.pow(size as u32));

let mut h = 0;
world.all_reduce_into(
&(rank + 1),
&mut h,
&UserOperation::commutative(|x, y| {
let x: &[Rank] = x.downcast().unwrap();
let y: &mut [Rank] = y.downcast().unwrap();
for (&x_i, y_i) in x.iter().zip(y) {
*y_i += x_i;
}
}),
);
assert_eq!(h, size * (size + 1) / 2);
test_user_operations(universe.world());
}
14 changes: 13 additions & 1 deletion src/collective.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,19 @@
//! - **5.12**: Nonblocking collective operations,
//! `MPI_Ialltoallw()`, `MPI_Ireduce_scatter()`

use std::{fmt, mem, ptr};
use std::{mem, ptr};
#[cfg(feature = "user-operations")]
use std::fmt;
#[cfg(feature = "user-operations")]
use std::os::raw::{c_int, c_void};

#[cfg(feature = "user-operations")]
use libffi::high::Closure4;

use ffi;
use ffi::{MPI_Op, MPI_Request};

#[cfg(feature = "user-operations")]
use datatype::{DatatypeRef, DynBuffer, DynBufferMut};
use datatype::traits::*;
use raw::traits::*;
Expand Down Expand Up @@ -1527,17 +1532,20 @@ impl<T> Erased for T {}
/// # Examples
///
/// See `examples/reduce.rs` and `examples/immediate_reduce.rs`
#[cfg(feature = "user-operations")]
pub struct UserOperation<'a> {
op: MPI_Op,
anchor: Box<Erased + 'a>, // keeps the internal data alive
}

#[cfg(feature = "user-operations")]
impl<'a> fmt::Debug for UserOperation<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_tuple("UserOperation").field(&self.op).finish()
}
}

#[cfg(feature = "user-operations")]
impl<'a> Drop for UserOperation<'a> {
fn drop(&mut self) {
unsafe {
Expand All @@ -1546,15 +1554,18 @@ impl<'a> Drop for UserOperation<'a> {
}
}

#[cfg(feature = "user-operations")]
unsafe impl<'a> AsRaw for UserOperation<'a> {
type Raw = MPI_Op;
fn as_raw(&self) -> Self::Raw {
self.op
}
}

#[cfg(feature = "user-operations")]
impl<'a, 'b> Operation for &'b UserOperation<'a> {}

#[cfg(feature = "user-operations")]
impl<'a> UserOperation<'a> {
/// Define an operation using a closure. The operation must be associative.
///
Expand Down Expand Up @@ -1629,6 +1640,7 @@ impl<'a> UserOperation<'a> {
}
}

#[cfg(feature = "user-operations")]
unsafe fn user_operation_landing_pad<F>(
function: &F,
mut invec: *mut c_void,
Expand Down
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@
use std::os::raw::c_int;

extern crate conv;
#[cfg(feature = "user-operations")]
extern crate libffi;

/// The raw C language MPI API
Expand Down

0 comments on commit ca8e6d7

Please sign in to comment.