Skip to content

Commit

Permalink
Clean up gating on concurrent feature (SpectralSequences#140)
Browse files Browse the repository at this point in the history
* Introduce `maybe-rayon` crate

* Adapt rest of codebase
  • Loading branch information
JoeyBF authored Nov 25, 2023
1 parent 4d99891 commit 8075e0a
Show file tree
Hide file tree
Showing 19 changed files with 264 additions and 262 deletions.
6 changes: 4 additions & 2 deletions ext/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ algebra = { path = "crates/algebra", default-features = false, features = [
bivec = { path = "crates/bivec" }
chart = { path = "crates/chart" }
fp = { path = "crates/fp", default-features = false }
maybe-rayon = { path = "crates/maybe-rayon" }
once = { path = "crates/once" }
query = { path = "crates/query" }
sseq = { path = "crates/sseq", default-features = false }
Expand All @@ -30,7 +31,6 @@ dashmap = "4.0.0"
itertools = { version = "0.10.0", default-features = false, features = [
"use_alloc",
] }
rayon = { version = "1.5", optional = true }
rustc-hash = "1.1.0"
serde_json = { version = "1.0.0", features = ["preserve_order"] }

Expand All @@ -54,9 +54,9 @@ cache-multiplication = ["algebra/cache-multiplication"]
concurrent = [
"algebra/concurrent",
"fp/concurrent",
"maybe-rayon/concurrent",
"once/concurrent",
"sseq/concurrent",
"rayon",
]
odd-primes = ["fp/odd-primes", "algebra/odd-primes", "sseq/odd-primes"]
logging = []
Expand All @@ -68,7 +68,9 @@ members = [
"crates/bivec",
"crates/chart",
"crates/fp",
"crates/maybe-rayon",
"crates/once",
"crates/query",
"crates/sseq",
]

Expand Down
5 changes: 2 additions & 3 deletions ext/crates/algebra/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ crate-type = ["cdylib", "rlib"]
[dependencies]
bivec = { path = "../bivec" }
fp = { path = "../fp", default-features = false }
maybe-rayon = { path = "../maybe-rayon" }
once = { path = "../once" }

anyhow = "1.0.0"
Expand All @@ -26,8 +27,6 @@ rustc-hash = "1.1.0"
serde = { version = "1.0.0", features = ["derive"], optional = true }
serde_json = { version = "1.0.0", optional = true }

rayon = { version = "1.5", optional = true }

[dev-dependencies]
bencher = "0.1.5"
expect-test = "1.1.0"
Expand All @@ -36,7 +35,7 @@ rstest = "0.17.0"
[features]
default = ["odd-primes", "json"]
cache-multiplication = []
concurrent = ["rayon", "fp/concurrent"]
concurrent = ["fp/concurrent", "maybe-rayon/concurrent"]
json = ["serde", "serde_json", "bivec/json", "fp/json"]
odd-primes = ["fp/odd-primes"]

Expand Down
29 changes: 10 additions & 19 deletions ext/crates/algebra/src/module/homomorphism/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,6 @@ use fp::matrix::{AugmentedMatrix, Matrix, MatrixSliceMut, QuasiInverse, Subspace
use fp::prime::ValidPrime;
use fp::vector::{Slice, SliceMut};

#[cfg(feature = "concurrent")]
use rayon::prelude::*;

mod free_module_homomorphism;
mod full_module_homomorphism;
mod generic_zero_homomorphism;
Expand All @@ -22,6 +19,9 @@ pub use generic_zero_homomorphism::GenericZeroHomomorphism;
pub use hom_pullback::HomPullback;
pub use quotient_homomorphism::{QuotientHomomorphism, QuotientHomomorphismSource};

#[allow(unused_imports)]
use maybe_rayon::prelude::*;

/// Each `ModuleHomomorphism` may come with auxiliary data, namely the kernel, image and
/// quasi_inverse at each degree (the quasi-inverse is a map that is a right inverse when
/// restricted to the image). These are computed via
Expand Down Expand Up @@ -122,14 +122,8 @@ pub trait ModuleHomomorphism: Send + Sync {
return;
}

#[cfg(not(feature = "concurrent"))]
for (i, row) in matrix.iter_mut().enumerate() {
self.apply_to_basis_element(row, 1, degree, i);
}

#[cfg(feature = "concurrent")]
matrix
.par_iter_mut()
.maybe_par_iter_mut()
.enumerate()
.for_each(|(i, row)| self.apply_to_basis_element(row, 1, degree, i));
}
Expand All @@ -142,15 +136,12 @@ pub trait ModuleHomomorphism: Send + Sync {
return matrix;
}

#[cfg(not(feature = "concurrent"))]
for (row, &v) in matrix.iter_mut().zip(inputs) {
self.apply_to_basis_element(row.as_slice_mut(), 1, degree, v);
}

#[cfg(feature = "concurrent")]
matrix.par_iter_mut().enumerate().for_each(|(i, row)| {
self.apply_to_basis_element(row.as_slice_mut(), 1, degree, inputs[i])
});
matrix
.maybe_par_iter_mut()
.enumerate()
.for_each(|(i, row)| {
self.apply_to_basis_element(row.as_slice_mut(), 1, degree, inputs[i])
});

matrix
}
Expand Down
4 changes: 2 additions & 2 deletions ext/crates/fp/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ itertools = { version = "0.10.0", default-features = false }
serde = { version = "1.0.0", optional = true }
serde_json = { version = "1.0.0", optional = true }

rayon = { version = "1.5", optional = true }
maybe-rayon = { path = "../maybe-rayon" }

[dev-dependencies]
criterion = { version = "0.3.5", features = ["html_reports"] }
Expand All @@ -28,7 +28,7 @@ build_const = "0.2.2"

[features]
default = ["odd-primes"]
concurrent = ["rayon"]
concurrent = ["maybe-rayon/concurrent"]
json = ["serde_json", "serde"]
odd-primes = []

Expand Down
18 changes: 10 additions & 8 deletions ext/crates/fp/src/matrix/matrix_inner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ use std::io::{Read, Write};
use std::ops::{Index, IndexMut};

use itertools::Itertools;
#[cfg(feature = "concurrent")]
use rayon::prelude::*;

use maybe_rayon::prelude::*;

/// A matrix! In particular, a matrix with values in F_p. The way we store matrices means it is
/// easier to perform row operations than column operations, and the way we use matrices means we
Expand Down Expand Up @@ -281,9 +281,10 @@ impl Matrix {
self.vectors.iter_mut()
}

#[cfg(feature = "concurrent")]
pub fn par_iter_mut(&mut self) -> impl IndexedParallelIterator<Item = &mut FpVector> + '_ {
self.vectors.par_iter_mut()
pub fn maybe_par_iter_mut(
&mut self,
) -> impl MaybeIndexedParallelIterator<Item = &mut FpVector> + '_ {
self.vectors.maybe_par_iter_mut()
}
}

Expand Down Expand Up @@ -1160,12 +1161,13 @@ impl<'a> MatrixSliceMut<'a> {
.map(move |x| x.slice_mut(start, end))
}

#[cfg(feature = "concurrent")]
pub fn par_iter_mut(&mut self) -> impl IndexedParallelIterator<Item = SliceMut> + '_ {
pub fn maybe_par_iter_mut(
&mut self,
) -> impl MaybeIndexedParallelIterator<Item = SliceMut> + '_ {
let start = self.col_start;
let end = self.col_end;
self.vectors
.par_iter_mut()
.maybe_par_iter_mut()
.map(move |x| x.slice_mut(start, end))
}

Expand Down
13 changes: 13 additions & 0 deletions ext/crates/maybe-rayon/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
[package]
name = "maybe-rayon"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
rayon = { version = "1.8.0", optional = true }

[features]
default = []
concurrent = ["rayon"]
64 changes: 64 additions & 0 deletions ext/crates/maybe-rayon/src/concurrent.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
pub mod prelude {
use rayon::prelude::*;

pub use rayon::iter::{IndexedParallelIterator, ParallelIterator};

pub trait MaybeParallelIterator: ParallelIterator {}

pub trait MaybeIndexedParallelIterator: IndexedParallelIterator {}

pub trait MaybeIntoParallelIterator: IntoParallelIterator {
fn maybe_into_par_iter(self) -> Self::Iter;
}

pub trait MaybeIntoParallelRefMutIterator<'data>: IntoParallelRefMutIterator<'data> {
fn maybe_par_iter_mut(&'data mut self) -> Self::Iter;
}

// Implementations

impl<I: ParallelIterator> MaybeParallelIterator for I {}

impl<I: IndexedParallelIterator> MaybeIndexedParallelIterator for I {}

impl<I: IntoParallelIterator> MaybeIntoParallelIterator for I {
fn maybe_into_par_iter(self) -> Self::Iter {
self.into_par_iter()
}
}

impl<'data, I: IntoParallelRefMutIterator<'data> + ?Sized>
MaybeIntoParallelRefMutIterator<'data> for I
{
fn maybe_par_iter_mut(&'data mut self) -> Self::Iter {
self.par_iter_mut()
}
}
}

pub fn join<A, B, RA, RB>(oper_a: A, oper_b: B) -> (RA, RB)
where
A: FnOnce() -> RA + Send,
B: FnOnce() -> RB + Send,
RA: Send,
RB: Send,
{
rayon::join(oper_a, oper_b)
}

pub type Scope<'scope> = rayon::Scope<'scope>;

pub fn scope<'scope, OP, R>(op: OP) -> R
where
OP: FnOnce(&Scope<'scope>) -> R + Send,
R: Send,
{
rayon::scope(op)
}

pub fn in_place_scope<'scope, OP, R>(op: OP) -> R
where
OP: FnOnce(&Scope<'scope>) -> R,
{
rayon::in_place_scope(op)
}
9 changes: 9 additions & 0 deletions ext/crates/maybe-rayon/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#[cfg(feature = "concurrent")]
pub mod concurrent;
#[cfg(feature = "concurrent")]
pub use concurrent::*;

#[cfg(not(feature = "concurrent"))]
pub mod sequential;
#[cfg(not(feature = "concurrent"))]
pub use sequential::*;
78 changes: 78 additions & 0 deletions ext/crates/maybe-rayon/src/sequential.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
pub mod prelude {
pub trait MaybeParallelIterator: Iterator {}

pub trait MaybeIndexedParallelIterator: Iterator {}

pub trait MaybeIntoParallelIterator: IntoIterator {
type Iter;

fn maybe_into_par_iter(self) -> Self::Iter;
}

pub trait MaybeIntoParallelRefMutIterator<'data> {
type Iter;

fn maybe_par_iter_mut(&'data mut self) -> Self::Iter;
}

// Implementations

impl<I: Iterator> MaybeParallelIterator for I {}

impl<I: Iterator> MaybeIndexedParallelIterator for I {}

impl<I: IntoIterator> MaybeIntoParallelIterator for I {
type Iter = Self::IntoIter;

fn maybe_into_par_iter(self) -> Self::Iter {
self.into_iter()
}
}

impl<'data, I: 'data + ?Sized> MaybeIntoParallelRefMutIterator<'data> for I
where
&'data mut I: IntoIterator,
{
type Iter = <&'data mut I as IntoIterator>::IntoIter;

fn maybe_par_iter_mut(&'data mut self) -> Self::Iter {
self.into_iter()
}
}
}

pub struct Scope<'scope>(&'scope ());

impl<'scope> Scope<'scope> {
pub fn spawn<BODY>(&self, body: BODY)
where
BODY: FnOnce(&Scope<'scope>) + Send + 'scope,
{
body(self)
}
}

pub fn join<A, B, RA, RB>(oper_a: A, oper_b: B) -> (RA, RB)
where
A: FnOnce() -> RA + Send,
B: FnOnce() -> RB + Send,
RA: Send,
RB: Send,
{
(oper_a(), oper_b())
}

pub fn scope<'scope, OP, R>(op: OP) -> R
where
OP: FnOnce(&Scope<'scope>) -> R + Send,
R: Send,
{
op(&Scope(&()))
}

pub fn in_place_scope<'scope, OP, R>(op: OP) -> R
where
OP: FnOnce(&Scope<'scope>) -> R,
{
op(&Scope(&()))
}
5 changes: 2 additions & 3 deletions ext/crates/once/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,14 @@ edition = "2021"

[dependencies]
bivec = { path = "../bivec" }

rayon = { version = "1", optional = true }
maybe-rayon = { path = "../maybe-rayon" }

[dev-dependencies]
criterion = "0.3"

[features]
default = []
concurrent = ["rayon"]
concurrent = ["maybe-rayon/concurrent"]

[[bench]]
name = "criterion"
Expand Down
Loading

0 comments on commit 8075e0a

Please sign in to comment.