Merge pull request #74 from str4d/bellman-multicore
Place bellman multicore operations behind a (default) feature flag
This commit is contained in:
commit
c2d0a7d048
|
@ -13,16 +13,17 @@ rand = "0.4"
|
||||||
bit-vec = "0.4.4"
|
bit-vec = "0.4.4"
|
||||||
ff = { path = "../ff" }
|
ff = { path = "../ff" }
|
||||||
futures = "0.1"
|
futures = "0.1"
|
||||||
futures-cpupool = "0.1"
|
futures-cpupool = { version = "0.1", optional = true }
|
||||||
group = { path = "../group" }
|
group = { path = "../group" }
|
||||||
num_cpus = "1"
|
num_cpus = { version = "1", optional = true }
|
||||||
crossbeam = "0.3"
|
crossbeam = { version = "0.3", optional = true }
|
||||||
pairing = { path = "../pairing", optional = true }
|
pairing = { path = "../pairing", optional = true }
|
||||||
byteorder = "1"
|
byteorder = "1"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
groth16 = ["pairing"]
|
groth16 = ["pairing"]
|
||||||
default = ["groth16"]
|
multicore = ["futures-cpupool", "crossbeam", "num_cpus"]
|
||||||
|
default = ["groth16", "multicore"]
|
||||||
|
|
||||||
[[test]]
|
[[test]]
|
||||||
name = "mimc"
|
name = "mimc"
|
||||||
|
|
|
@ -3,13 +3,18 @@ extern crate group;
|
||||||
#[cfg(feature = "pairing")]
|
#[cfg(feature = "pairing")]
|
||||||
extern crate pairing;
|
extern crate pairing;
|
||||||
extern crate rand;
|
extern crate rand;
|
||||||
extern crate num_cpus;
|
|
||||||
extern crate futures;
|
extern crate futures;
|
||||||
extern crate futures_cpupool;
|
|
||||||
extern crate bit_vec;
|
extern crate bit_vec;
|
||||||
extern crate crossbeam;
|
|
||||||
extern crate byteorder;
|
extern crate byteorder;
|
||||||
|
|
||||||
|
#[cfg(feature = "multicore")]
|
||||||
|
extern crate crossbeam;
|
||||||
|
#[cfg(feature = "multicore")]
|
||||||
|
extern crate futures_cpupool;
|
||||||
|
#[cfg(feature = "multicore")]
|
||||||
|
extern crate num_cpus;
|
||||||
|
|
||||||
pub mod multicore;
|
pub mod multicore;
|
||||||
mod multiexp;
|
mod multiexp;
|
||||||
pub mod domain;
|
pub mod domain;
|
||||||
|
|
|
@ -4,103 +4,165 @@
|
||||||
//! crossbeam but may be extended in the future to
|
//! crossbeam but may be extended in the future to
|
||||||
//! allow for various parallelism strategies.
|
//! allow for various parallelism strategies.
|
||||||
|
|
||||||
use num_cpus;
|
#[cfg(feature = "multicore")]
|
||||||
use futures::{Future, IntoFuture, Poll};
|
mod implementation {
|
||||||
use futures_cpupool::{CpuPool, CpuFuture};
|
use num_cpus;
|
||||||
use crossbeam::{self, Scope};
|
use futures::{Future, IntoFuture, Poll};
|
||||||
|
use futures_cpupool::{CpuPool, CpuFuture};
|
||||||
|
use crossbeam::{self, Scope};
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Worker {
|
pub struct Worker {
|
||||||
cpus: usize,
|
cpus: usize,
|
||||||
pool: CpuPool
|
pool: CpuPool
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Worker {
|
impl Worker {
|
||||||
// We don't expose this outside the library so that
|
// We don't expose this outside the library so that
|
||||||
// all `Worker` instances have the same number of
|
// all `Worker` instances have the same number of
|
||||||
// CPUs configured.
|
// CPUs configured.
|
||||||
pub(crate) fn new_with_cpus(cpus: usize) -> Worker {
|
pub(crate) fn new_with_cpus(cpus: usize) -> Worker {
|
||||||
Worker {
|
Worker {
|
||||||
cpus: cpus,
|
cpus: cpus,
|
||||||
pool: CpuPool::new(cpus)
|
pool: CpuPool::new(cpus)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new() -> Worker {
|
||||||
|
Self::new_with_cpus(num_cpus::get())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn log_num_cpus(&self) -> u32 {
|
||||||
|
log2_floor(self.cpus)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn compute<F, R>(
|
||||||
|
&self, f: F
|
||||||
|
) -> WorkerFuture<R::Item, R::Error>
|
||||||
|
where F: FnOnce() -> R + Send + 'static,
|
||||||
|
R: IntoFuture + 'static,
|
||||||
|
R::Future: Send + 'static,
|
||||||
|
R::Item: Send + 'static,
|
||||||
|
R::Error: Send + 'static
|
||||||
|
{
|
||||||
|
WorkerFuture {
|
||||||
|
future: self.pool.spawn_fn(f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn scope<'a, F, R>(
|
||||||
|
&self,
|
||||||
|
elements: usize,
|
||||||
|
f: F
|
||||||
|
) -> R
|
||||||
|
where F: FnOnce(&Scope<'a>, usize) -> R
|
||||||
|
{
|
||||||
|
let chunk_size = if elements < self.cpus {
|
||||||
|
1
|
||||||
|
} else {
|
||||||
|
elements / self.cpus
|
||||||
|
};
|
||||||
|
|
||||||
|
crossbeam::scope(|scope| {
|
||||||
|
f(scope, chunk_size)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new() -> Worker {
|
pub struct WorkerFuture<T, E> {
|
||||||
Self::new_with_cpus(num_cpus::get())
|
future: CpuFuture<T, E>
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn log_num_cpus(&self) -> u32 {
|
impl<T: Send + 'static, E: Send + 'static> Future for WorkerFuture<T, E> {
|
||||||
log2_floor(self.cpus)
|
type Item = T;
|
||||||
}
|
type Error = E;
|
||||||
|
|
||||||
pub fn compute<F, R>(
|
fn poll(&mut self) -> Poll<Self::Item, Self::Error>
|
||||||
&self, f: F
|
{
|
||||||
) -> WorkerFuture<R::Item, R::Error>
|
self.future.poll()
|
||||||
where F: FnOnce() -> R + Send + 'static,
|
|
||||||
R: IntoFuture + 'static,
|
|
||||||
R::Future: Send + 'static,
|
|
||||||
R::Item: Send + 'static,
|
|
||||||
R::Error: Send + 'static
|
|
||||||
{
|
|
||||||
WorkerFuture {
|
|
||||||
future: self.pool.spawn_fn(f)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn scope<'a, F, R>(
|
fn log2_floor(num: usize) -> u32 {
|
||||||
&self,
|
assert!(num > 0);
|
||||||
elements: usize,
|
|
||||||
f: F
|
|
||||||
) -> R
|
|
||||||
where F: FnOnce(&Scope<'a>, usize) -> R
|
|
||||||
{
|
|
||||||
let chunk_size = if elements < self.cpus {
|
|
||||||
1
|
|
||||||
} else {
|
|
||||||
elements / self.cpus
|
|
||||||
};
|
|
||||||
|
|
||||||
crossbeam::scope(|scope| {
|
let mut pow = 0;
|
||||||
f(scope, chunk_size)
|
|
||||||
})
|
while (1 << (pow+1)) <= num {
|
||||||
|
pow += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
pow
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_log2_floor() {
|
||||||
|
assert_eq!(log2_floor(1), 0);
|
||||||
|
assert_eq!(log2_floor(2), 1);
|
||||||
|
assert_eq!(log2_floor(3), 1);
|
||||||
|
assert_eq!(log2_floor(4), 2);
|
||||||
|
assert_eq!(log2_floor(5), 2);
|
||||||
|
assert_eq!(log2_floor(6), 2);
|
||||||
|
assert_eq!(log2_floor(7), 2);
|
||||||
|
assert_eq!(log2_floor(8), 3);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct WorkerFuture<T, E> {
|
#[cfg(not(feature = "multicore"))]
|
||||||
future: CpuFuture<T, E>
|
mod implementation {
|
||||||
}
|
use futures::{future, Future, IntoFuture, Poll};
|
||||||
|
|
||||||
impl<T: Send + 'static, E: Send + 'static> Future for WorkerFuture<T, E> {
|
#[derive(Clone)]
|
||||||
type Item = T;
|
pub struct Worker;
|
||||||
type Error = E;
|
|
||||||
|
|
||||||
fn poll(&mut self) -> Poll<Self::Item, Self::Error>
|
impl Worker {
|
||||||
{
|
pub fn new() -> Worker {
|
||||||
self.future.poll()
|
Worker
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn log_num_cpus(&self) -> u32 {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn compute<F, R>(&self, f: F) -> R::Future
|
||||||
|
where
|
||||||
|
F: FnOnce() -> R + Send + 'static,
|
||||||
|
R: IntoFuture + 'static,
|
||||||
|
R::Future: Send + 'static,
|
||||||
|
R::Item: Send + 'static,
|
||||||
|
R::Error: Send + 'static,
|
||||||
|
{
|
||||||
|
f().into_future()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn scope<F, R>(&self, elements: usize, f: F) -> R
|
||||||
|
where
|
||||||
|
F: FnOnce(&DummyScope, usize) -> R,
|
||||||
|
{
|
||||||
|
f(&DummyScope, elements)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct WorkerFuture<T, E> {
|
||||||
|
future: future::FutureResult<T, E>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Send + 'static, E: Send + 'static> Future for WorkerFuture<T, E> {
|
||||||
|
type Item = T;
|
||||||
|
type Error = E;
|
||||||
|
|
||||||
|
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
|
||||||
|
self.future.poll()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct DummyScope;
|
||||||
|
|
||||||
|
impl DummyScope {
|
||||||
|
pub fn spawn<F: FnOnce()>(&self, f: F) {
|
||||||
|
f();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn log2_floor(num: usize) -> u32 {
|
pub use self::implementation::*;
|
||||||
assert!(num > 0);
|
|
||||||
|
|
||||||
let mut pow = 0;
|
|
||||||
|
|
||||||
while (1 << (pow+1)) <= num {
|
|
||||||
pow += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
pow
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_log2_floor() {
|
|
||||||
assert_eq!(log2_floor(1), 0);
|
|
||||||
assert_eq!(log2_floor(2), 1);
|
|
||||||
assert_eq!(log2_floor(3), 1);
|
|
||||||
assert_eq!(log2_floor(4), 2);
|
|
||||||
assert_eq!(log2_floor(5), 2);
|
|
||||||
assert_eq!(log2_floor(6), 2);
|
|
||||||
assert_eq!(log2_floor(7), 2);
|
|
||||||
assert_eq!(log2_floor(8), 3);
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in New Issue