diff --git a/.vscode/settings.json b/.vscode/settings.json index 47cbecb37..98ecbcd81 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -7,6 +7,6 @@ "rust-analyzer.cargo.features": [ "all-algorithms", "all-scenarios", - "mpi-partitioning" + "all-partitionings", ], } diff --git a/Cargo.lock b/Cargo.lock index 1e73f11f8..447740505 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1144,7 +1144,6 @@ name = "necsim-partitioning-core" version = "0.1.0" dependencies = [ "anyhow", - "contracts", "necsim-core", "necsim-core-bond", "serde", @@ -1155,7 +1154,6 @@ name = "necsim-partitioning-monolithic" version = "0.1.0" dependencies = [ "anyhow", - "contracts", "necsim-core", "necsim-core-bond", "necsim-impls-std", @@ -1189,7 +1187,6 @@ version = "0.1.0" dependencies = [ "anyhow", "bit-set", - "contracts", "humantime-serde", "necsim-core", "necsim-core-bond", diff --git a/necsim/impls/no-std/src/parallelisation/independent/individuals.rs b/necsim/impls/no-std/src/parallelisation/independent/individuals.rs index 6182e0947..5810ef688 100644 --- a/necsim/impls/no-std/src/parallelisation/independent/individuals.rs +++ b/necsim/impls/no-std/src/parallelisation/independent/individuals.rs @@ -36,7 +36,6 @@ use super::{reporter::IgnoreProgressReporterProxy, DedupCache}; #[allow(clippy::type_complexity)] pub fn simulate< - 'p, M: MathsCore, H: Habitat, G: PrimeableRng, @@ -57,7 +56,7 @@ pub fn simulate< NeverImmigrationEntry, >, R: Reporter, - P: LocalPartition<'p, R>, + P: LocalPartition, L: IntoIterator, >( simulation: &mut Simulation< diff --git a/necsim/impls/no-std/src/parallelisation/independent/landscape.rs b/necsim/impls/no-std/src/parallelisation/independent/landscape.rs index 2a28c8ea3..f5540bd1f 100644 --- a/necsim/impls/no-std/src/parallelisation/independent/landscape.rs +++ b/necsim/impls/no-std/src/parallelisation/independent/landscape.rs @@ -39,7 +39,6 @@ use super::{reporter::IgnoreProgressReporterProxy, DedupCache}; #[allow(clippy::type_complexity, clippy::too_many_lines)] pub fn simulate< - 'p, M: MathsCore, H: Habitat, C: Decomposition, @@ -62,7 +61,7 @@ pub fn simulate< NeverImmigrationEntry, >, R: Reporter, - P: LocalPartition<'p, R>, + P: LocalPartition, L: IntoIterator, >( simulation: &mut Simulation< diff --git a/necsim/impls/no-std/src/parallelisation/independent/monolithic/mod.rs b/necsim/impls/no-std/src/parallelisation/independent/monolithic/mod.rs index 6bc67feaa..639558a66 100644 --- a/necsim/impls/no-std/src/parallelisation/independent/monolithic/mod.rs +++ b/necsim/impls/no-std/src/parallelisation/independent/monolithic/mod.rs @@ -41,7 +41,6 @@ use reporter::{ #[allow(clippy::type_complexity, clippy::too_many_lines)] pub fn simulate< - 'p, M: MathsCore, H: Habitat, G: PrimeableRng, @@ -62,7 +61,7 @@ pub fn simulate< NeverImmigrationEntry, >, R: Reporter, - P: LocalPartition<'p, R>, + P: LocalPartition, L: IntoIterator, >( simulation: &mut Simulation< diff --git a/necsim/impls/no-std/src/parallelisation/independent/monolithic/reporter/live.rs b/necsim/impls/no-std/src/parallelisation/independent/monolithic/reporter/live.rs index 24bb72672..0c22a60bc 100644 --- a/necsim/impls/no-std/src/parallelisation/independent/monolithic/reporter/live.rs +++ b/necsim/impls/no-std/src/parallelisation/independent/monolithic/reporter/live.rs @@ -13,18 +13,16 @@ use necsim_partitioning_core::LocalPartition; use super::WaterLevelReporterProxy; #[allow(clippy::module_name_repetitions)] -pub struct LiveWaterLevelReporterProxy<'l, 'p, R: Reporter, P: LocalPartition<'p, R>> { +pub struct LiveWaterLevelReporterProxy<'p, R: Reporter, P: LocalPartition> { water_level: NonNegativeF64, slow_events: Vec, fast_events: Vec, - local_partition: &'l mut P, - _marker: PhantomData<(&'p (), R)>, + local_partition: &'p mut P, + _marker: PhantomData, } -impl<'l, 'p, R: Reporter, P: LocalPartition<'p, R>> fmt::Debug - for LiveWaterLevelReporterProxy<'l, 'p, R, P> -{ +impl<'p, R: Reporter, P: LocalPartition> fmt::Debug for LiveWaterLevelReporterProxy<'p, R, P> { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { struct EventBufferLen(usize); @@ -42,9 +40,7 @@ impl<'l, 'p, R: Reporter, P: LocalPartition<'p, R>> fmt::Debug } } -impl<'l, 'p, R: Reporter, P: LocalPartition<'p, R>> Reporter - for LiveWaterLevelReporterProxy<'l, 'p, R, P> -{ +impl<'p, R: Reporter, P: LocalPartition> Reporter for LiveWaterLevelReporterProxy<'p, R, P> { impl_report!(speciation(&mut self, speciation: MaybeUsed) { if speciation.event_time < self.water_level { self.slow_events.push(speciation.clone().into()); @@ -65,10 +61,10 @@ impl<'l, 'p, R: Reporter, P: LocalPartition<'p, R>> Reporter } #[contract_trait] -impl<'l, 'p, R: Reporter, P: LocalPartition<'p, R>> WaterLevelReporterProxy<'l, 'p, R, P> - for LiveWaterLevelReporterProxy<'l, 'p, R, P> +impl<'p, R: Reporter, P: LocalPartition> WaterLevelReporterProxy<'p, R, P> + for LiveWaterLevelReporterProxy<'p, R, P> { - fn new(capacity: usize, local_partition: &'l mut P) -> Self { + fn new(capacity: usize, local_partition: &'p mut P) -> Self { info!("Events will be reported using the live water-level algorithm ..."); Self { @@ -77,7 +73,7 @@ impl<'l, 'p, R: Reporter, P: LocalPartition<'p, R>> WaterLevelReporterProxy<'l, fast_events: Vec::with_capacity(capacity), local_partition, - _marker: PhantomData::<(&'p (), R)>, + _marker: PhantomData::, } } @@ -119,9 +115,7 @@ impl<'l, 'p, R: Reporter, P: LocalPartition<'p, R>> WaterLevelReporterProxy<'l, } } -impl<'l, 'p, R: Reporter, P: LocalPartition<'p, R>> Drop - for LiveWaterLevelReporterProxy<'l, 'p, R, P> -{ +impl<'p, R: Reporter, P: LocalPartition> Drop for LiveWaterLevelReporterProxy<'p, R, P> { fn drop(&mut self) { // Report all events below the water level in sorted order self.slow_events.sort_unstable(); diff --git a/necsim/impls/no-std/src/parallelisation/independent/monolithic/reporter/mod.rs b/necsim/impls/no-std/src/parallelisation/independent/monolithic/reporter/mod.rs index 7df56366e..5c4e5dfa2 100644 --- a/necsim/impls/no-std/src/parallelisation/independent/monolithic/reporter/mod.rs +++ b/necsim/impls/no-std/src/parallelisation/independent/monolithic/reporter/mod.rs @@ -13,7 +13,7 @@ mod recorded; #[allow(clippy::inline_always, clippy::inline_fn_without_body)] #[allow(clippy::no_effect_underscore_binding)] #[contract_trait] -pub trait WaterLevelReporterProxy<'l, 'p, R: Reporter, P: LocalPartition<'p, R>>: +pub trait WaterLevelReporterProxy<'p, R: Reporter, P: LocalPartition>: Sized + Reporter< ReportSpeciation = R::ReportSpeciation, @@ -21,7 +21,7 @@ pub trait WaterLevelReporterProxy<'l, 'p, R: Reporter, P: LocalPartition<'p, R>> ReportProgress = False, > { - fn new(capacity: usize, local_partition: &'l mut P) -> Self; + fn new(capacity: usize, local_partition: &'p mut P) -> Self; fn water_level(&self) -> NonNegativeF64; @@ -36,24 +36,23 @@ pub trait WaterLevelReporterProxy<'l, 'p, R: Reporter, P: LocalPartition<'p, R>> pub enum WaterLevelReporterStrategy {} pub trait WaterLevelReporterConstructor< - 'l, 'p, IsLive: Boolean, R: Reporter, - P: 'l + LocalPartition<'p, R, IsLive = IsLive>, + P: 'p + LocalPartition, > { - type WaterLevelReporter: WaterLevelReporterProxy<'l, 'p, R, P>; + type WaterLevelReporter: WaterLevelReporterProxy<'p, R, P>; } -impl<'l, 'p, IsLive: Boolean, R: Reporter, P: 'l + LocalPartition<'p, R, IsLive = IsLive>> - WaterLevelReporterConstructor<'l, 'p, IsLive, R, P> for WaterLevelReporterStrategy +impl<'p, IsLive: Boolean, R: Reporter, P: 'p + LocalPartition> + WaterLevelReporterConstructor<'p, IsLive, R, P> for WaterLevelReporterStrategy { - default type WaterLevelReporter = live::LiveWaterLevelReporterProxy<'l, 'p, R, P>; + default type WaterLevelReporter = live::LiveWaterLevelReporterProxy<'p, R, P>; } -impl<'l, 'p, R: Reporter, P: 'l + LocalPartition<'p, R, IsLive = False>> - WaterLevelReporterConstructor<'l, 'p, False, R, P> for WaterLevelReporterStrategy +impl<'p, R: Reporter, P: 'p + LocalPartition> + WaterLevelReporterConstructor<'p, False, R, P> for WaterLevelReporterStrategy { - type WaterLevelReporter = recorded::RecordedWaterLevelReporterProxy<'l, 'p, R, P>; + type WaterLevelReporter = recorded::RecordedWaterLevelReporterProxy<'p, R, P>; } diff --git a/necsim/impls/no-std/src/parallelisation/independent/monolithic/reporter/recorded.rs b/necsim/impls/no-std/src/parallelisation/independent/monolithic/reporter/recorded.rs index 455313de5..cebf47912 100644 --- a/necsim/impls/no-std/src/parallelisation/independent/monolithic/reporter/recorded.rs +++ b/necsim/impls/no-std/src/parallelisation/independent/monolithic/reporter/recorded.rs @@ -8,15 +8,15 @@ use necsim_partitioning_core::LocalPartition; use super::WaterLevelReporterProxy; #[allow(clippy::module_name_repetitions)] -pub struct RecordedWaterLevelReporterProxy<'l, 'p, R: Reporter, P: LocalPartition<'p, R>> { +pub struct RecordedWaterLevelReporterProxy<'p, R: Reporter, P: LocalPartition> { water_level: NonNegativeF64, - local_partition: &'l mut P, - _marker: PhantomData<(&'p (), R)>, + local_partition: &'p mut P, + _marker: PhantomData, } -impl<'l, 'p, R: Reporter, P: LocalPartition<'p, R>> fmt::Debug - for RecordedWaterLevelReporterProxy<'l, 'p, R, P> +impl<'p, R: Reporter, P: LocalPartition> fmt::Debug + for RecordedWaterLevelReporterProxy<'p, R, P> { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { fmt.debug_struct(stringify!(RecordedWaterLevelReporterProxy)) @@ -25,9 +25,7 @@ impl<'l, 'p, R: Reporter, P: LocalPartition<'p, R>> fmt::Debug } } -impl<'l, 'p, R: Reporter, P: LocalPartition<'p, R>> Reporter - for RecordedWaterLevelReporterProxy<'l, 'p, R, P> -{ +impl<'p, R: Reporter, P: LocalPartition> Reporter for RecordedWaterLevelReporterProxy<'p, R, P> { impl_report!(speciation(&mut self, speciation: MaybeUsed) { self.local_partition.get_reporter().report_speciation(speciation.into()); }); @@ -40,17 +38,17 @@ impl<'l, 'p, R: Reporter, P: LocalPartition<'p, R>> Reporter } #[contract_trait] -impl<'l, 'p, R: Reporter, P: LocalPartition<'p, R>> WaterLevelReporterProxy<'l, 'p, R, P> - for RecordedWaterLevelReporterProxy<'l, 'p, R, P> +impl<'p, R: Reporter, P: LocalPartition> WaterLevelReporterProxy<'p, R, P> + for RecordedWaterLevelReporterProxy<'p, R, P> { - fn new(_capacity: usize, local_partition: &'l mut P) -> Self { + fn new(_capacity: usize, local_partition: &'p mut P) -> Self { info!("Events will be reported using the recorded water-level algorithm ..."); Self { water_level: NonNegativeF64::zero(), local_partition, - _marker: PhantomData::<(&'p (), R)>, + _marker: PhantomData::, } } diff --git a/necsim/impls/no-std/src/parallelisation/independent/reporter.rs b/necsim/impls/no-std/src/parallelisation/independent/reporter.rs index a8e84caa1..76c178e10 100644 --- a/necsim/impls/no-std/src/parallelisation/independent/reporter.rs +++ b/necsim/impls/no-std/src/parallelisation/independent/reporter.rs @@ -4,31 +4,27 @@ use necsim_core::{impl_report, reporter::Reporter}; use necsim_partitioning_core::LocalPartition; -pub struct IgnoreProgressReporterProxy<'l, 'p, R: Reporter, P: LocalPartition<'p, R>> { - local_partition: &'l mut P, - _marker: PhantomData<(&'p (), R)>, +pub struct IgnoreProgressReporterProxy<'p, R: Reporter, P: LocalPartition> { + local_partition: &'p mut P, + _marker: PhantomData, } -impl<'l, 'p, R: Reporter, P: LocalPartition<'p, R>> fmt::Debug - for IgnoreProgressReporterProxy<'l, 'p, R, P> -{ +impl<'p, R: Reporter, P: LocalPartition> fmt::Debug for IgnoreProgressReporterProxy<'p, R, P> { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { fmt.debug_struct(stringify!(IgnoreProgressReporterProxy)) .finish() } } -impl<'l, 'p, R: Reporter, P: LocalPartition<'p, R>> Reporter - for IgnoreProgressReporterProxy<'l, 'p, R, P> -{ +impl<'p, R: Reporter, P: LocalPartition> Reporter for IgnoreProgressReporterProxy<'p, R, P> { impl_report!(speciation(&mut self, speciation: MaybeUsed< - <

>::Reporter as Reporter + <

>::Reporter as Reporter >::ReportSpeciation>) { self.local_partition.get_reporter().report_speciation(speciation.into()); }); impl_report!(dispersal(&mut self, dispersal: MaybeUsed< - <

>::Reporter as Reporter + <

>::Reporter as Reporter >::ReportDispersal>) { self.local_partition.get_reporter().report_dispersal(dispersal.into()); }); @@ -36,11 +32,11 @@ impl<'l, 'p, R: Reporter, P: LocalPartition<'p, R>> Reporter impl_report!(progress(&mut self, _progress: Ignored) {}); } -impl<'l, 'p, R: Reporter, P: LocalPartition<'p, R>> IgnoreProgressReporterProxy<'l, 'p, R, P> { - pub fn from(local_partition: &'l mut P) -> Self { +impl<'p, R: Reporter, P: LocalPartition> IgnoreProgressReporterProxy<'p, R, P> { + pub fn from(local_partition: &'p mut P) -> Self { Self { local_partition, - _marker: PhantomData::<(&'p (), R)>, + _marker: PhantomData::, } } diff --git a/necsim/impls/no-std/src/parallelisation/monolithic/averaging.rs b/necsim/impls/no-std/src/parallelisation/monolithic/averaging.rs index b255c2ab0..3f9f2ab5d 100644 --- a/necsim/impls/no-std/src/parallelisation/monolithic/averaging.rs +++ b/necsim/impls/no-std/src/parallelisation/monolithic/averaging.rs @@ -23,7 +23,6 @@ use crate::{ #[allow(clippy::type_complexity)] pub fn simulate< - 'p, M: MathsCore, H: Habitat, G: RngCore, @@ -48,7 +47,7 @@ pub fn simulate< BufferedImmigrationEntry, >, P: Reporter, - L: LocalPartition<'p, P>, + L: LocalPartition

, >( simulation: &mut Simulation< M, diff --git a/necsim/impls/no-std/src/parallelisation/monolithic/lockstep.rs b/necsim/impls/no-std/src/parallelisation/monolithic/lockstep.rs index f1ff75edc..b1cb18051 100644 --- a/necsim/impls/no-std/src/parallelisation/monolithic/lockstep.rs +++ b/necsim/impls/no-std/src/parallelisation/monolithic/lockstep.rs @@ -23,7 +23,6 @@ use crate::{ #[allow(clippy::type_complexity)] pub fn simulate< - 'p, M: MathsCore, H: Habitat, G: RngCore, @@ -48,7 +47,7 @@ pub fn simulate< BufferedImmigrationEntry, >, P: Reporter, - L: LocalPartition<'p, P>, + L: LocalPartition

, >( simulation: &mut Simulation< M, diff --git a/necsim/impls/no-std/src/parallelisation/monolithic/monolithic.rs b/necsim/impls/no-std/src/parallelisation/monolithic/monolithic.rs index 86c1f2418..2fd8aebcb 100644 --- a/necsim/impls/no-std/src/parallelisation/monolithic/monolithic.rs +++ b/necsim/impls/no-std/src/parallelisation/monolithic/monolithic.rs @@ -22,7 +22,6 @@ use crate::{ #[allow(clippy::type_complexity)] pub fn simulate< - 'p, M: MathsCore, H: Habitat, G: RngCore, @@ -34,7 +33,7 @@ pub fn simulate< E: EventSampler, A: ActiveLineageSampler, P: Reporter, - L: LocalPartition<'p, P>, + L: LocalPartition

, >( simulation: &mut Simulation< M, diff --git a/necsim/impls/no-std/src/parallelisation/monolithic/optimistic.rs b/necsim/impls/no-std/src/parallelisation/monolithic/optimistic.rs index ee9a55a49..70bcc2e59 100644 --- a/necsim/impls/no-std/src/parallelisation/monolithic/optimistic.rs +++ b/necsim/impls/no-std/src/parallelisation/monolithic/optimistic.rs @@ -28,7 +28,6 @@ use super::reporter::BufferingReporterProxy; #[allow(clippy::type_complexity)] pub fn simulate< - 'p, M: MathsCore, H: Habitat, G: RngCore, @@ -53,7 +52,7 @@ pub fn simulate< BufferedImmigrationEntry, >, P: Reporter, - L: LocalPartition<'p, P>, + L: LocalPartition

, >( simulation: &mut Simulation< M, diff --git a/necsim/impls/no-std/src/parallelisation/monolithic/optimistic_lockstep.rs b/necsim/impls/no-std/src/parallelisation/monolithic/optimistic_lockstep.rs index d9cdab94d..b09b1cc8f 100644 --- a/necsim/impls/no-std/src/parallelisation/monolithic/optimistic_lockstep.rs +++ b/necsim/impls/no-std/src/parallelisation/monolithic/optimistic_lockstep.rs @@ -23,7 +23,6 @@ use crate::{ #[allow(clippy::type_complexity)] pub fn simulate< - 'p, M: MathsCore, H: Habitat, G: RngCore, @@ -48,7 +47,7 @@ pub fn simulate< BufferedImmigrationEntry, >, P: Reporter, - L: LocalPartition<'p, P>, + L: LocalPartition

, >( simulation: &mut Simulation< M, diff --git a/necsim/impls/no-std/src/parallelisation/monolithic/reporter.rs b/necsim/impls/no-std/src/parallelisation/monolithic/reporter.rs index fa181ffff..3e8278d65 100644 --- a/necsim/impls/no-std/src/parallelisation/monolithic/reporter.rs +++ b/necsim/impls/no-std/src/parallelisation/monolithic/reporter.rs @@ -9,15 +9,13 @@ use necsim_core::{ use necsim_partitioning_core::LocalPartition; -pub struct BufferingReporterProxy<'l, 'p, R: Reporter, P: LocalPartition<'p, R>> { - local_partition: &'l mut P, +pub struct BufferingReporterProxy<'p, R: Reporter, P: LocalPartition> { + local_partition: &'p mut P, event_buffer: Vec, - _marker: PhantomData<(&'p (), R)>, + _marker: PhantomData, } -impl<'l, 'p, R: Reporter, P: LocalPartition<'p, R>> fmt::Debug - for BufferingReporterProxy<'l, 'p, R, P> -{ +impl<'p, R: Reporter, P: LocalPartition> fmt::Debug for BufferingReporterProxy<'p, R, P> { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { struct EventBufferLen(usize); @@ -33,34 +31,32 @@ impl<'l, 'p, R: Reporter, P: LocalPartition<'p, R>> fmt::Debug } } -impl<'l, 'p, R: Reporter, P: LocalPartition<'p, R>> Reporter - for BufferingReporterProxy<'l, 'p, R, P> -{ +impl<'p, R: Reporter, P: LocalPartition> Reporter for BufferingReporterProxy<'p, R, P> { impl_report!(speciation(&mut self, speciation: MaybeUsed< - <

>::Reporter as Reporter + <

>::Reporter as Reporter >::ReportSpeciation>) { self.event_buffer.push(speciation.clone().into()); }); impl_report!(dispersal(&mut self, dispersal: MaybeUsed< - <

>::Reporter as Reporter + <

>::Reporter as Reporter >::ReportDispersal>) { self.event_buffer.push(dispersal.clone().into()); }); impl_report!(progress(&mut self, progress: MaybeUsed< - <

>::Reporter as Reporter + <

>::Reporter as Reporter >::ReportProgress>) { self.local_partition.get_reporter().report_progress(progress.into()); }); } -impl<'l, 'p, R: Reporter, P: LocalPartition<'p, R>> BufferingReporterProxy<'l, 'p, R, P> { - pub fn from(local_partition: &'l mut P) -> Self { +impl<'p, R: Reporter, P: LocalPartition> BufferingReporterProxy<'p, R, P> { + pub fn from(local_partition: &'p mut P) -> Self { Self { local_partition, event_buffer: Vec::new(), - _marker: PhantomData::<(&'p (), R)>, + _marker: PhantomData::, } } diff --git a/necsim/impls/std/src/event_log/recorder.rs b/necsim/impls/std/src/event_log/recorder.rs index 828bfdbec..7660af723 100644 --- a/necsim/impls/std/src/event_log/recorder.rs +++ b/necsim/impls/std/src/event_log/recorder.rs @@ -77,8 +77,6 @@ impl EventLogRecorder { /// /// Fails to construct iff `path` is not a writable directory. pub fn try_new(path: &Path, segment_capacity: NonZeroUsize) -> Result { - let path = path.canonicalize()?; - if let Some(parent) = path.parent() { fs::create_dir_all(parent).with_context(|| { format!("failed to ensure that the parent path for {path:?} exists") @@ -87,7 +85,7 @@ impl EventLogRecorder { Self { segment_capacity, - directory: path, + directory: path.to_owned(), segment_index: 0_usize, buffer: Vec::with_capacity(segment_capacity.get()), @@ -116,7 +114,8 @@ impl EventLogRecorder { .create_valid_directory() } - fn create_valid_directory(self) -> Result { + fn create_valid_directory(mut self) -> Result { + // TODO: MPI cannot newly co-create all entries fs::create_dir(&self.directory).with_context(|| { format!( "failed to newly create the directory {:?}\n\nIf you are starting a new \ @@ -127,6 +126,8 @@ impl EventLogRecorder { ) })?; + self.directory = self.directory.canonicalize()?; + let metadata = fs::metadata(&self.directory)?; if !metadata.is_dir() { diff --git a/necsim/partitioning/core/Cargo.toml b/necsim/partitioning/core/Cargo.toml index ad52d3dd9..35ee78a5f 100644 --- a/necsim/partitioning/core/Cargo.toml +++ b/necsim/partitioning/core/Cargo.toml @@ -12,5 +12,4 @@ necsim-core = { path = "../../core" } necsim-core-bond = { path = "../../core/bond" } anyhow = { version = "1.0", default-features = false } -contracts = "0.6.3" serde = { version = "1.0", default-features = false, features = ["derive"] } diff --git a/necsim/partitioning/core/src/lib.rs b/necsim/partitioning/core/src/lib.rs index f4a719a14..24a31160a 100644 --- a/necsim/partitioning/core/src/lib.rs +++ b/necsim/partitioning/core/src/lib.rs @@ -3,9 +3,6 @@ extern crate alloc; -#[macro_use] -extern crate contracts; - use core::ops::ControlFlow; use necsim_core::{ @@ -14,21 +11,21 @@ use necsim_core::{ }; use necsim_core_bond::PositiveF64; -pub mod context; pub mod iterator; pub mod partition; +pub mod reporter; -use context::ReporterContext; use partition::{Partition, PartitionSize}; +use reporter::{FinalisableReporter, ReporterContext}; -#[allow(clippy::inline_always, clippy::inline_fn_without_body)] -#[contract_trait] pub trait Partitioning: Sized { - type LocalPartition<'p, R: Reporter>: LocalPartition<'p, R>; + type LocalPartition: LocalPartition; + type FinalisableReporter: FinalisableReporter; type Auxiliary; fn get_size(&self) -> PartitionSize; + #[allow(clippy::missing_errors_doc)] fn with_local_partition< R: Reporter, P: ReporterContext, @@ -39,9 +36,9 @@ pub trait Partitioning: Sized { reporter_context: P, auxiliary: Self::Auxiliary, args: A, - inner: for<'p> fn(Self::LocalPartition<'p, R>, A) -> Q, + inner: fn(&mut Self::LocalPartition, A) -> Q, fold: fn(Q, Q) -> Q, - ) -> anyhow::Result; + ) -> anyhow::Result<(Q, Self::FinalisableReporter)>; } pub trait Data: Send + Clone {} @@ -54,15 +51,12 @@ pub enum MigrationMode { Hold, } -#[allow(clippy::inline_always, clippy::inline_fn_without_body)] -#[contract_trait] -pub trait LocalPartition<'p, R: Reporter>: Sized { +pub trait LocalPartition: Sized { type Reporter: Reporter; type IsLive: Boolean; type ImmigrantIterator<'a>: Iterator where - Self: 'a, - 'p: 'a; + Self: 'a; fn get_reporter(&mut self) -> &mut Self::Reporter; @@ -73,18 +67,15 @@ pub trait LocalPartition<'p, R: Reporter>: Sized { emigrants: &mut E, emigration_mode: MigrationMode, immigration_mode: MigrationMode, - ) -> Self::ImmigrantIterator<'a> - where - 'p: 'a; + ) -> Self::ImmigrantIterator<'a>; fn reduce_vote_any(&mut self, vote: bool) -> bool; + #[allow(clippy::missing_errors_doc)] fn reduce_vote_min_time(&mut self, local_time: PositiveF64) -> Result; fn wait_for_termination(&mut self) -> ControlFlow<(), ()>; fn report_progress_sync(&mut self, remaining: u64); - - fn finalise_reporting(self); } diff --git a/necsim/partitioning/core/src/context.rs b/necsim/partitioning/core/src/reporter.rs similarity index 83% rename from necsim/partitioning/core/src/context.rs rename to necsim/partitioning/core/src/reporter.rs index af875dc47..bcb103e62 100644 --- a/necsim/partitioning/core/src/context.rs +++ b/necsim/partitioning/core/src/reporter.rs @@ -11,3 +11,8 @@ pub trait ReporterContext: core::fmt::Debug { self, ) -> anyhow::Result>; } + +#[allow(clippy::module_name_repetitions)] +pub trait FinalisableReporter { + fn finalise(self); +} diff --git a/necsim/partitioning/monolithic/Cargo.toml b/necsim/partitioning/monolithic/Cargo.toml index a4b96c672..f3da028db 100644 --- a/necsim/partitioning/monolithic/Cargo.toml +++ b/necsim/partitioning/monolithic/Cargo.toml @@ -14,5 +14,4 @@ necsim-impls-std = { path = "../../impls/std" } necsim-partitioning-core = { path = "../core" } anyhow = { version = "1.0", default-features = false } -contracts = "0.6.3" serde = "1.0" diff --git a/necsim/partitioning/monolithic/src/lib.rs b/necsim/partitioning/monolithic/src/lib.rs index 306a4ee51..10c33685e 100644 --- a/necsim/partitioning/monolithic/src/lib.rs +++ b/necsim/partitioning/monolithic/src/lib.rs @@ -1,8 +1,5 @@ #![deny(clippy::pedantic)] -#[macro_use] -extern crate contracts; - use std::{fmt, ops::ControlFlow}; use serde::{Deserialize, Deserializer, Serialize, Serializer}; @@ -10,14 +7,17 @@ use serde::{Deserialize, Deserializer, Serialize, Serializer}; use necsim_core::{ impl_report, lineage::MigratingLineage, - reporter::{boolean::True, Reporter}, + reporter::{ + boolean::{False, True}, + FilteredReporter, Reporter, + }, }; use necsim_core_bond::PositiveF64; use necsim_partitioning_core::{ - context::ReporterContext, iterator::ImmigrantPopIterator, partition::{Partition, PartitionSize}, + reporter::{FinalisableReporter, ReporterContext}, LocalPartition, MigrationMode, Partitioning, }; @@ -49,10 +49,10 @@ impl<'de> Deserialize<'de> for MonolithicPartitioning { } } -#[contract_trait] impl Partitioning for MonolithicPartitioning { type Auxiliary = Option; - type LocalPartition<'p, R: Reporter> = MonolithicLocalPartition; + type FinalisableReporter = FinalisableMonolithicReporter; + type LocalPartition = MonolithicLocalPartition; fn get_size(&self) -> PartitionSize { PartitionSize::MONOLITHIC @@ -66,23 +66,25 @@ impl Partitioning for MonolithicPartitioning { reporter_context: P, event_log: Self::Auxiliary, args: A, - inner: for<'p> fn(Self::LocalPartition<'p, R>, A) -> Q, + inner: fn(&mut Self::LocalPartition, A) -> Q, _fold: fn(Q, Q) -> Q, - ) -> anyhow::Result { - let local_partition = if let Some(event_log) = event_log { + ) -> anyhow::Result<(Q, Self::FinalisableReporter)> { + let mut local_partition = if let Some(event_log) = event_log { MonolithicLocalPartition::Recorded(Box::new( - recorded::RecordedMonolithicLocalPartition::try_from_context_and_recorder( - reporter_context, + recorded::RecordedMonolithicLocalPartition::from_reporter_and_recorder( + reporter_context.try_build()?, event_log, - )?, + ), )) } else { MonolithicLocalPartition::Live(Box::new( - live::LiveMonolithicLocalPartition::try_from_context(reporter_context)?, + live::LiveMonolithicLocalPartition::from_reporter(reporter_context.try_build()?), )) }; - Ok(inner(local_partition, args)) + let result = inner(&mut local_partition, args); + + Ok((result, local_partition.into_reporter())) } } @@ -93,9 +95,8 @@ pub enum MonolithicLocalPartition { Recorded(Box>), } -#[contract_trait] -impl<'p, R: Reporter> LocalPartition<'p, R> for MonolithicLocalPartition { - type ImmigrantIterator<'a> = ImmigrantPopIterator<'a> where 'p: 'a, R: 'a; +impl LocalPartition for MonolithicLocalPartition { + type ImmigrantIterator<'a> = ImmigrantPopIterator<'a> where R: 'a; // pessimistic type IsLive = True; type Reporter = Self; @@ -116,10 +117,7 @@ impl<'p, R: Reporter> LocalPartition<'p, R> for MonolithicLocalPartition { emigrants: &mut E, emigration_mode: MigrationMode, immigration_mode: MigrationMode, - ) -> Self::ImmigrantIterator<'a> - where - 'p: 'a, - { + ) -> Self::ImmigrantIterator<'a> { match self { Self::Live(partition) => { partition.migrate_individuals(emigrants, emigration_mode, immigration_mode) @@ -160,13 +158,6 @@ impl<'p, R: Reporter> LocalPartition<'p, R> for MonolithicLocalPartition { Self::Recorded(partition) => partition.report_progress_sync(remaining), } } - - fn finalise_reporting(self) { - match self { - Self::Live(partition) => partition.finalise_reporting(), - Self::Recorded(partition) => partition.finalise_reporting(), - } - } } impl Reporter for MonolithicLocalPartition { @@ -203,3 +194,28 @@ impl Reporter for MonolithicLocalPartition { } }); } + +impl MonolithicLocalPartition { + fn into_reporter(self) -> FinalisableMonolithicReporter { + match self { + Self::Live(partition) => FinalisableMonolithicReporter::Live(partition.into_reporter()), + Self::Recorded(partition) => { + FinalisableMonolithicReporter::Recorded(partition.into_reporter()) + }, + } + } +} + +pub enum FinalisableMonolithicReporter { + Live(FilteredReporter), + Recorded(FilteredReporter), +} + +impl FinalisableReporter for FinalisableMonolithicReporter { + fn finalise(self) { + match self { + Self::Live(reporter) => reporter.finalise(), + Self::Recorded(reporter) => reporter.finalise(), + } + } +} diff --git a/necsim/partitioning/monolithic/src/live.rs b/necsim/partitioning/monolithic/src/live.rs index 8b839e690..313226682 100644 --- a/necsim/partitioning/monolithic/src/live.rs +++ b/necsim/partitioning/monolithic/src/live.rs @@ -7,8 +7,7 @@ use necsim_core::{ use necsim_core_bond::PositiveF64; use necsim_partitioning_core::{ - context::ReporterContext, iterator::ImmigrantPopIterator, partition::Partition, LocalPartition, - MigrationMode, + iterator::ImmigrantPopIterator, partition::Partition, LocalPartition, MigrationMode, }; #[allow(clippy::module_name_repetitions)] @@ -34,9 +33,8 @@ impl fmt::Debug for LiveMonolithicLocalPartition { } } -#[contract_trait] -impl<'p, R: Reporter> LocalPartition<'p, R> for LiveMonolithicLocalPartition { - type ImmigrantIterator<'a> = ImmigrantPopIterator<'a> where 'p: 'a, R: 'a; +impl LocalPartition for LiveMonolithicLocalPartition { + type ImmigrantIterator<'a> = ImmigrantPopIterator<'a> where R: 'a; type IsLive = True; type Reporter = FilteredReporter; @@ -53,10 +51,7 @@ impl<'p, R: Reporter> LocalPartition<'p, R> for LiveMonolithicLocalPartition emigrants: &mut E, _emigration_mode: MigrationMode, _immigration_mode: MigrationMode, - ) -> Self::ImmigrantIterator<'a> - where - 'p: 'a, - { + ) -> Self::ImmigrantIterator<'a> { for (_, emigrant) in emigrants { self.loopback.push(emigrant); } @@ -86,10 +81,6 @@ impl<'p, R: Reporter> LocalPartition<'p, R> for LiveMonolithicLocalPartition fn report_progress_sync(&mut self, remaining: u64) { self.reporter.report_progress(&remaining.into()); } - - fn finalise_reporting(self) { - self.reporter.finalise(); - } } impl LiveMonolithicLocalPartition { @@ -100,12 +91,7 @@ impl LiveMonolithicLocalPartition { } } - /// # Errors - /// - /// Returns any error which occured while building the context's reporter - pub(crate) fn try_from_context>( - context: P, - ) -> anyhow::Result { - Ok(Self::from_reporter(context.try_build()?)) + pub(crate) fn into_reporter(self) -> FilteredReporter { + self.reporter } } diff --git a/necsim/partitioning/monolithic/src/recorded.rs b/necsim/partitioning/monolithic/src/recorded.rs index fae4c9d6c..aeea2495a 100644 --- a/necsim/partitioning/monolithic/src/recorded.rs +++ b/necsim/partitioning/monolithic/src/recorded.rs @@ -15,8 +15,7 @@ use necsim_core_bond::PositiveF64; use necsim_impls_std::event_log::recorder::EventLogRecorder; use necsim_partitioning_core::{ - context::ReporterContext, iterator::ImmigrantPopIterator, partition::Partition, LocalPartition, - MigrationMode, + iterator::ImmigrantPopIterator, partition::Partition, LocalPartition, MigrationMode, }; #[allow(clippy::module_name_repetitions)] @@ -44,9 +43,8 @@ impl fmt::Debug for RecordedMonolithicLocalPartition { } } -#[contract_trait] -impl<'p, R: Reporter> LocalPartition<'p, R> for RecordedMonolithicLocalPartition { - type ImmigrantIterator<'a> = ImmigrantPopIterator<'a> where 'p: 'a, R: 'a; +impl LocalPartition for RecordedMonolithicLocalPartition { + type ImmigrantIterator<'a> = ImmigrantPopIterator<'a> where R: 'a; type IsLive = False; type Reporter = Self; @@ -63,10 +61,7 @@ impl<'p, R: Reporter> LocalPartition<'p, R> for RecordedMonolithicLocalPartition emigrants: &mut E, _emigration_mode: MigrationMode, _immigration_mode: MigrationMode, - ) -> Self::ImmigrantIterator<'a> - where - 'p: 'a, - { + ) -> Self::ImmigrantIterator<'a> { for (_, emigrant) in emigrants { self.loopback.push(emigrant); } @@ -96,27 +91,24 @@ impl<'p, R: Reporter> LocalPartition<'p, R> for RecordedMonolithicLocalPartition fn report_progress_sync(&mut self, remaining: u64) { self.reporter.report_progress(&remaining.into()); } - - fn finalise_reporting(self) { - self.reporter.finalise(); - } } impl RecordedMonolithicLocalPartition { - /// # Errors - /// - /// Returns any error which occured while building the context's reporter - pub(crate) fn try_from_context_and_recorder>( - context: P, + pub(crate) fn from_reporter_and_recorder( + reporter: FilteredReporter, mut recorder: EventLogRecorder, - ) -> anyhow::Result { + ) -> Self { recorder.set_event_filter(R::ReportSpeciation::VALUE, R::ReportDispersal::VALUE); - Ok(Self { - reporter: context.try_build()?, + Self { + reporter, recorder, loopback: Vec::new(), - }) + } + } + + pub(crate) fn into_reporter(self) -> FilteredReporter { + self.reporter } } diff --git a/necsim/partitioning/mpi/src/lib.rs b/necsim/partitioning/mpi/src/lib.rs index d4a4259e1..b400c439e 100644 --- a/necsim/partitioning/mpi/src/lib.rs +++ b/necsim/partitioning/mpi/src/lib.rs @@ -19,11 +19,19 @@ use serde_derive_state::DeserializeState; use serde_state::{DeserializeState, Deserializer}; use thiserror::Error; -use necsim_core::{lineage::MigratingLineage, reporter::Reporter}; +use necsim_core::{ + lineage::MigratingLineage, + reporter::{ + boolean::{False, True}, + FilteredReporter, Reporter, + }, +}; use necsim_impls_std::event_log::recorder::EventLogRecorder; use necsim_partitioning_core::{ - context::ReporterContext, partition::PartitionSize, Data, Partitioning, + partition::PartitionSize, + reporter::{FinalisableReporter, ReporterContext}, + Data, Partitioning, }; mod partition; @@ -156,10 +164,10 @@ impl MpiPartitioning { } } -#[contract_trait] impl Partitioning for MpiPartitioning { type Auxiliary = Option; - type LocalPartition<'p, R: Reporter> = MpiLocalPartition<'p, R>; + type FinalisableReporter = FinalisableMpiReporter; + type LocalPartition = MpiLocalPartition<'static, R>; fn get_size(&self) -> PartitionSize { #[allow(clippy::cast_sign_loss)] @@ -183,9 +191,9 @@ impl Partitioning for MpiPartitioning { reporter_context: P, event_log: Self::Auxiliary, args: A, - inner: for<'p> fn(Self::LocalPartition<'p, R>, A) -> Q, + inner: fn(&mut Self::LocalPartition, A) -> Q, fold: fn(Q, Q) -> Q, - ) -> anyhow::Result { + ) -> anyhow::Result<(Q, Self::FinalisableReporter)> { let Some(event_log) = event_log else { anyhow::bail!(MpiLocalPartitionError::MissingEventLog) }; @@ -235,10 +243,16 @@ impl Partitioning for MpiPartitioning { self.progress_interval, ))) }; + // TODO: clean up to not expose the lifetime + // Safety: we only expose the partition through an outer reference + let mut local_partition: MpiLocalPartition<'static, R> = + unsafe { std::mem::transmute(local_partition) }; + + let local_result = inner(&mut local_partition, args); - let local_result = inner(local_partition, args); + let result = reduce_partitioning_data(&self.world, local_result, fold)?; - reduce_partitioning_data(&self.world, local_result, fold) + Ok((result, local_partition.into_reporter())) }) } } @@ -346,3 +360,16 @@ fn reduce_partitioning_data( Ok(folded) } + +pub enum FinalisableMpiReporter { + Root(FilteredReporter), + Parallel, +} + +impl FinalisableReporter for FinalisableMpiReporter { + fn finalise(self) { + if let Self::Root(reporter) = self { + reporter.finalise(); + } + } +} diff --git a/necsim/partitioning/mpi/src/partition/mod.rs b/necsim/partitioning/mpi/src/partition/mod.rs index d77255107..4561b1a15 100644 --- a/necsim/partitioning/mpi/src/partition/mod.rs +++ b/necsim/partitioning/mpi/src/partition/mod.rs @@ -21,6 +21,8 @@ pub use parallel::MpiParallelPartition; #[allow(clippy::module_name_repetitions)] pub use root::MpiRootPartition; +use crate::FinalisableMpiReporter; + #[allow(clippy::module_name_repetitions)] #[derive(Debug)] pub enum MpiLocalPartition<'p, R: Reporter> { @@ -28,8 +30,7 @@ pub enum MpiLocalPartition<'p, R: Reporter> { Parallel(Box>), } -#[contract_trait] -impl<'p, R: Reporter> LocalPartition<'p, R> for MpiLocalPartition<'p, R> { +impl<'p, R: Reporter> LocalPartition for MpiLocalPartition<'p, R> { type ImmigrantIterator<'a> = ImmigrantPopIterator<'a> where 'p: 'a, R: 'a; type IsLive = False; type Reporter = Self; @@ -50,10 +51,7 @@ impl<'p, R: Reporter> LocalPartition<'p, R> for MpiLocalPartition<'p, R> { emigrants: &mut E, emigration_mode: MigrationMode, immigration_mode: MigrationMode, - ) -> Self::ImmigrantIterator<'a> - where - 'p: 'a, - { + ) -> Self::ImmigrantIterator<'a> { match self { Self::Root(partition) => { partition.migrate_individuals(emigrants, emigration_mode, immigration_mode) @@ -94,13 +92,6 @@ impl<'p, R: Reporter> LocalPartition<'p, R> for MpiLocalPartition<'p, R> { Self::Parallel(partition) => partition.report_progress_sync(remaining), } } - - fn finalise_reporting(self) { - match self { - Self::Root(partition) => partition.finalise_reporting(), - Self::Parallel(partition) => partition.finalise_reporting(), - } - } } impl<'p, R: Reporter> Reporter for MpiLocalPartition<'p, R> { @@ -137,3 +128,12 @@ impl<'p, R: Reporter> Reporter for MpiLocalPartition<'p, R> { } }); } + +impl<'p, R: Reporter> MpiLocalPartition<'p, R> { + pub(crate) fn into_reporter(self) -> FinalisableMpiReporter { + match self { + Self::Root(partition) => FinalisableMpiReporter::Root(partition.into_reporter()), + Self::Parallel(_) => FinalisableMpiReporter::Parallel, + } + } +} diff --git a/necsim/partitioning/mpi/src/partition/parallel.rs b/necsim/partitioning/mpi/src/partition/parallel.rs index 85b41d576..f0eea8412 100644 --- a/necsim/partitioning/mpi/src/partition/parallel.rs +++ b/necsim/partitioning/mpi/src/partition/parallel.rs @@ -81,8 +81,7 @@ impl<'p, R: Reporter> MpiParallelPartition<'p, R> { } } -#[contract_trait] -impl<'p, R: Reporter> LocalPartition<'p, R> for MpiParallelPartition<'p, R> { +impl<'p, R: Reporter> LocalPartition for MpiParallelPartition<'p, R> { type ImmigrantIterator<'a> = ImmigrantPopIterator<'a> where 'p: 'a, R: 'a; type IsLive = False; type Reporter = Self; @@ -100,10 +99,7 @@ impl<'p, R: Reporter> LocalPartition<'p, R> for MpiParallelPartition<'p, R> { emigrants: &mut E, emigration_mode: MigrationMode, immigration_mode: MigrationMode, - ) -> Self::ImmigrantIterator<'a> - where - 'p: 'a, - { + ) -> Self::ImmigrantIterator<'a> { self.common .migrate_individuals(emigrants, emigration_mode, immigration_mode) } @@ -131,10 +127,6 @@ impl<'p, R: Reporter> LocalPartition<'p, R> for MpiParallelPartition<'p, R> { root_process.gather_into(&remaining); } - - fn finalise_reporting(self) { - std::mem::drop(self); - } } impl<'p, R: Reporter> Reporter for MpiParallelPartition<'p, R> { diff --git a/necsim/partitioning/mpi/src/partition/root.rs b/necsim/partitioning/mpi/src/partition/root.rs index 2cdd8c467..67ac4f956 100644 --- a/necsim/partitioning/mpi/src/partition/root.rs +++ b/necsim/partitioning/mpi/src/partition/root.rs @@ -1,6 +1,5 @@ use std::{ fmt, - mem::ManuallyDrop, num::Wrapping, ops::ControlFlow, time::{Duration, Instant}, @@ -33,9 +32,8 @@ pub struct MpiRootPartition<'p, R: Reporter> { common: MpiCommonPartition<'p>, all_remaining: Box<[u64]>, last_report_time: Instant, - reporter: ManuallyDrop>, + reporter: FilteredReporter, recorder: EventLogRecorder, - finalised: bool, progress_interval: Duration, } @@ -45,19 +43,6 @@ impl<'p, R: Reporter> fmt::Debug for MpiRootPartition<'p, R> { } } -impl<'p, R: Reporter> Drop for MpiRootPartition<'p, R> { - fn drop(&mut self) { - // Safety: destructor is only run once - if self.finalised { - unsafe { ManuallyDrop::take(&mut self.reporter) }.finalise(); - } else { - unsafe { - ManuallyDrop::drop(&mut self.reporter); - } - } - } -} - impl<'p, R: Reporter> MpiRootPartition<'p, R> { #[must_use] pub(crate) fn new( @@ -90,16 +75,14 @@ impl<'p, R: Reporter> MpiRootPartition<'p, R> { common, all_remaining, last_report_time: now.checked_sub(progress_interval).unwrap_or(now), - reporter: ManuallyDrop::new(reporter), + reporter, recorder, - finalised: false, progress_interval, } } } -#[contract_trait] -impl<'p, R: Reporter> LocalPartition<'p, R> for MpiRootPartition<'p, R> { +impl<'p, R: Reporter> LocalPartition for MpiRootPartition<'p, R> { type ImmigrantIterator<'a> = ImmigrantPopIterator<'a> where 'p: 'a, R: 'a; type IsLive = False; type Reporter = Self; @@ -117,10 +100,7 @@ impl<'p, R: Reporter> LocalPartition<'p, R> for MpiRootPartition<'p, R> { emigrants: &mut E, emigration_mode: MigrationMode, immigration_mode: MigrationMode, - ) -> Self::ImmigrantIterator<'a> - where - 'p: 'a, - { + ) -> Self::ImmigrantIterator<'a> { self.common .migrate_individuals(emigrants, emigration_mode, immigration_mode) } @@ -167,12 +147,6 @@ impl<'p, R: Reporter> LocalPartition<'p, R> for MpiRootPartition<'p, R> { .into(), ); } - - fn finalise_reporting(mut self) { - self.finalised = true; - - std::mem::drop(self); - } } impl<'p, R: Reporter> Reporter for MpiRootPartition<'p, R> { @@ -214,3 +188,9 @@ impl<'p, R: Reporter> Reporter for MpiRootPartition<'p, R> { } }); } + +impl<'p, R: Reporter> MpiRootPartition<'p, R> { + pub(crate) fn into_reporter(self) -> FilteredReporter { + self.reporter + } +} diff --git a/necsim/partitioning/threads/Cargo.toml b/necsim/partitioning/threads/Cargo.toml index b68ec01a4..ce161b3b2 100644 --- a/necsim/partitioning/threads/Cargo.toml +++ b/necsim/partitioning/threads/Cargo.toml @@ -13,7 +13,6 @@ necsim-core-bond = { path = "../../core/bond" } necsim-impls-std = { path = "../../impls/std" } necsim-partitioning-core = { path = "../../partitioning/core" } -contracts = "0.6.3" thiserror = "1.0" anyhow = "1.0" serde = "1.0" diff --git a/necsim/partitioning/threads/src/lib.rs b/necsim/partitioning/threads/src/lib.rs index c5bd442a2..ff40ca28d 100644 --- a/necsim/partitioning/threads/src/lib.rs +++ b/necsim/partitioning/threads/src/lib.rs @@ -1,8 +1,5 @@ #![deny(clippy::pedantic)] -#[macro_use] -extern crate contracts; - use std::{ fmt, num::Wrapping, @@ -24,7 +21,9 @@ use necsim_core::reporter::{ use necsim_impls_std::event_log::recorder::EventLogRecorder; use necsim_partitioning_core::{ - context::ReporterContext, partition::PartitionSize, Data, Partitioning, + partition::PartitionSize, + reporter::{FinalisableReporter, ReporterContext}, + Data, Partitioning, }; mod partition; @@ -120,10 +119,10 @@ impl ThreadsPartitioning { } } -#[contract_trait] impl Partitioning for ThreadsPartitioning { type Auxiliary = Option; - type LocalPartition<'p, R: Reporter> = ThreadsLocalPartition<'p, R>; + type FinalisableReporter = FinalisableThreadsReporter; + type LocalPartition = ThreadsLocalPartition; fn get_size(&self) -> PartitionSize { self.num_threads @@ -145,9 +144,9 @@ impl Partitioning for ThreadsPartitioning { reporter_context: P, event_log: Self::Auxiliary, args: A, - inner: for<'p> fn(Self::LocalPartition<'p, R>, A) -> Q, + inner: fn(&mut Self::LocalPartition, A) -> Q, fold: fn(Q, Q) -> Q, - ) -> anyhow::Result { + ) -> anyhow::Result<(Q, Self::FinalisableReporter)> { // TODO: add support for multithread live reporting let Some(event_log) = event_log else { anyhow::bail!(ThreadsLocalPartitionError::MissingEventLog) @@ -209,7 +208,7 @@ impl Partitioning for ThreadsPartitioning { .map( |((((partition, immigration_channel), event_log), progress_channel), args)| { scope.spawn(move || { - let local_partition = ThreadsLocalPartition::::new( + let mut local_partition = ThreadsLocalPartition::::new( partition, vote_any, vote_min_time, @@ -223,7 +222,7 @@ impl Partitioning for ThreadsPartitioning { sync_barrier, ); - inner(local_partition, args) + inner(&mut local_partition, args) }) }, ) @@ -257,7 +256,22 @@ impl Partitioning for ThreadsPartitioning { folded_result.expect("at least one threads partitioning result") }); - Ok(result) + Ok(( + result, + FinalisableThreadsReporter { + reporter: progress_reporter, + }, + )) + } +} + +pub struct FinalisableThreadsReporter { + reporter: FilteredReporter, +} + +impl FinalisableReporter for FinalisableThreadsReporter { + fn finalise(self) { + self.reporter.finalise(); } } diff --git a/necsim/partitioning/threads/src/partition.rs b/necsim/partitioning/threads/src/partition.rs index bf511a1ba..7995e146e 100644 --- a/necsim/partitioning/threads/src/partition.rs +++ b/necsim/partitioning/threads/src/partition.rs @@ -26,7 +26,7 @@ use necsim_partitioning_core::{partition::Partition, LocalPartition, MigrationMo use crate::vote::{AsyncVote, Vote}; #[allow(clippy::module_name_repetitions)] -pub struct ThreadsLocalPartition<'p, R: Reporter> { +pub struct ThreadsLocalPartition { partition: Partition, vote_any: Vote, vote_min_time: Vote<(PositiveF64, u32)>, @@ -44,16 +44,16 @@ pub struct ThreadsLocalPartition<'p, R: Reporter> { last_report_time: Instant, progress_interval: Duration, sync_barrier: Arc, - _marker: PhantomData<(&'p (), R)>, + _marker: PhantomData, } -impl<'p, R: Reporter> fmt::Debug for ThreadsLocalPartition<'p, R> { +impl fmt::Debug for ThreadsLocalPartition { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - fmt.debug_struct(stringify!(ThreadsRootPartition)).finish() + fmt.debug_struct(stringify!(ThreadsLocalPartition)).finish() } } -impl<'p, R: Reporter> ThreadsLocalPartition<'p, R> { +impl ThreadsLocalPartition { #[allow(clippy::too_many_arguments)] #[must_use] pub(crate) fn new( @@ -100,14 +100,13 @@ impl<'p, R: Reporter> ThreadsLocalPartition<'p, R> { last_report_time: now.checked_sub(progress_interval).unwrap_or(now), progress_interval, sync_barrier: sync_barrier.clone(), - _marker: PhantomData::<(&'p (), R)>, + _marker: PhantomData::, } } } -#[contract_trait] -impl<'p, R: Reporter> LocalPartition<'p, R> for ThreadsLocalPartition<'p, R> { - type ImmigrantIterator<'a> = ImmigrantPopIterator<'a> where 'p: 'a, R: 'a; +impl LocalPartition for ThreadsLocalPartition { + type ImmigrantIterator<'a> = ImmigrantPopIterator<'a> where R: 'a; type IsLive = False; type Reporter = Self; @@ -124,10 +123,7 @@ impl<'p, R: Reporter> LocalPartition<'p, R> for ThreadsLocalPartition<'p, R> { emigrants: &mut E, emigration_mode: MigrationMode, immigration_mode: MigrationMode, - ) -> Self::ImmigrantIterator<'a> - where - 'p: 'a, - { + ) -> Self::ImmigrantIterator<'a> { for (partition, emigrant) in emigrants { self.emigration_buffers[partition as usize].push(emigrant); } @@ -272,13 +268,9 @@ impl<'p, R: Reporter> LocalPartition<'p, R> for ThreadsLocalPartition<'p, R> { self.sync_barrier.wait(); } - - fn finalise_reporting(self) { - std::mem::drop(self); - } } -impl<'p, R: Reporter> Reporter for ThreadsLocalPartition<'p, R> { +impl Reporter for ThreadsLocalPartition { impl_report!(speciation(&mut self, speciation: MaybeUsed) { self.recorder.record_speciation(speciation); }); diff --git a/rustcoalescence/Cargo.toml b/rustcoalescence/Cargo.toml index 64778e42d..e24b3a8da 100644 --- a/rustcoalescence/Cargo.toml +++ b/rustcoalescence/Cargo.toml @@ -58,7 +58,7 @@ all-scenarios = [ mpi-partitioning = ["dep:necsim-partitioning-mpi"] threads-partitioning = ["dep:necsim-partitioning-threads"] -all-partitioning = [ +all-partitionings = [ "mpi-partitioning", "threads-partitioning", ] diff --git a/rustcoalescence/algorithms/cuda/src/launch.rs b/rustcoalescence/algorithms/cuda/src/launch.rs index 921da4fc3..b41adb591 100644 --- a/rustcoalescence/algorithms/cuda/src/launch.rs +++ b/rustcoalescence/algorithms/cuda/src/launch.rs @@ -50,12 +50,11 @@ use crate::{ #[allow(clippy::too_many_lines)] pub fn initialise_and_simulate< - 'p, M: MathsCore + Sync, G: PrimeableRng + RustToCuda + Sync, O: Scenario, R: Reporter, - P: LocalPartition<'p, R>, + P: LocalPartition, I: Iterator, L: CudaLineageStoreSampleInitialiser, Error: From, diff --git a/rustcoalescence/algorithms/cuda/src/lib.rs b/rustcoalescence/algorithms/cuda/src/lib.rs index c19913634..d6cee311a 100644 --- a/rustcoalescence/algorithms/cuda/src/lib.rs +++ b/rustcoalescence/algorithms/cuda/src/lib.rs @@ -258,7 +258,7 @@ where >, >, { - type Algorithm<'p, P: LocalPartition<'p, R>> = Self; + type Algorithm> = Self; fn get_logical_partition_size( args: &Self::Arguments, @@ -275,13 +275,12 @@ where } impl< - 'p, M: MathsCore + Sync, G: PrimeableRng + RustToCuda + Sync, O: Scenario, R: Reporter, - P: LocalPartition<'p, R>, - > Algorithm<'p, M, G, O, R, P> for CudaAlgorithm + P: LocalPartition, + > Algorithm for CudaAlgorithm where O::Habitat: RustToCuda + Sync, O::DispersalSampler: RustToCuda + Sync, diff --git a/rustcoalescence/algorithms/cuda/src/parallelisation/monolithic.rs b/rustcoalescence/algorithms/cuda/src/parallelisation/monolithic.rs index b049d3d9d..40fca7c02 100644 --- a/rustcoalescence/algorithms/cuda/src/parallelisation/monolithic.rs +++ b/rustcoalescence/algorithms/cuda/src/parallelisation/monolithic.rs @@ -45,8 +45,6 @@ type Result = std::result::Result; #[allow(clippy::type_complexity, clippy::too_many_lines)] pub fn simulate< - 'l, - 'p, M: MathsCore + Sync, H: Habitat + RustToCuda + Sync, G: PrimeableRng + RustToCuda + Sync, @@ -60,7 +58,7 @@ pub fn simulate< I: ImmigrationEntry + RustToCuda + Sync, A: SingularActiveLineageSampler + RustToCuda + Sync, P: Reporter, - L: LocalPartition<'p, P>, + L: LocalPartition

, LI: IntoIterator, >( simulation: &mut Simulation, @@ -84,7 +82,7 @@ pub fn simulate< lineages: LI, event_slice: EventSlice, pause_before: Option, - local_partition: &'l mut L, + local_partition: &mut L, ) -> Result<( Status, NonNegativeF64, diff --git a/rustcoalescence/algorithms/gillespie/src/arguments.rs b/rustcoalescence/algorithms/gillespie/src/arguments.rs index 910d03f04..82134aea9 100644 --- a/rustcoalescence/algorithms/gillespie/src/arguments.rs +++ b/rustcoalescence/algorithms/gillespie/src/arguments.rs @@ -117,7 +117,7 @@ pub fn get_gillespie_logical_partition_size( } #[must_use] -pub fn get_gillespie_logical_partition<'p, R: Reporter, P: LocalPartition<'p, R>>( +pub fn get_gillespie_logical_partition>( args: &GillespieArguments, local_partition: &P, ) -> Partition { diff --git a/rustcoalescence/algorithms/gillespie/src/event_skipping/initialiser/fixup.rs b/rustcoalescence/algorithms/gillespie/src/event_skipping/initialiser/fixup.rs index 7a440732f..39fd1b239 100644 --- a/rustcoalescence/algorithms/gillespie/src/event_skipping/initialiser/fixup.rs +++ b/rustcoalescence/algorithms/gillespie/src/event_skipping/initialiser/fixup.rs @@ -105,13 +105,12 @@ where fn init< 'h, - 'p, T: TrustedOriginSampler<'h, M, Habitat = O::Habitat>, S: GloballyCoherentLineageStore, X: EmigrationExit, I: ImmigrationEntry, Q: Reporter, - P: LocalPartition<'p, Q>, + P: LocalPartition, >( self, origin_sampler: T, diff --git a/rustcoalescence/algorithms/gillespie/src/event_skipping/initialiser/genesis.rs b/rustcoalescence/algorithms/gillespie/src/event_skipping/initialiser/genesis.rs index 790ed2bfc..27ac0ec69 100644 --- a/rustcoalescence/algorithms/gillespie/src/event_skipping/initialiser/genesis.rs +++ b/rustcoalescence/algorithms/gillespie/src/event_skipping/initialiser/genesis.rs @@ -56,13 +56,12 @@ where fn init< 'h, - 'p, T: TrustedOriginSampler<'h, M, Habitat = O::Habitat>, S: GloballyCoherentLineageStore, X: EmigrationExit, I: ImmigrationEntry, Q: Reporter, - P: LocalPartition<'p, Q>, + P: LocalPartition, >( self, origin_sampler: T, diff --git a/rustcoalescence/algorithms/gillespie/src/event_skipping/initialiser/mod.rs b/rustcoalescence/algorithms/gillespie/src/event_skipping/initialiser/mod.rs index 70490f920..be13d3387 100644 --- a/rustcoalescence/algorithms/gillespie/src/event_skipping/initialiser/mod.rs +++ b/rustcoalescence/algorithms/gillespie/src/event_skipping/initialiser/mod.rs @@ -59,13 +59,12 @@ pub trait EventSkippingLineageStoreSampleInitialiser< #[allow(clippy::type_complexity)] fn init< 'h, - 'p, T: TrustedOriginSampler<'h, M, Habitat = O::Habitat>, S: GloballyCoherentLineageStore, X: EmigrationExit, I: ImmigrationEntry, Q: Reporter, - P: LocalPartition<'p, Q>, + P: LocalPartition, >( self, origin_sampler: T, diff --git a/rustcoalescence/algorithms/gillespie/src/event_skipping/initialiser/resume.rs b/rustcoalescence/algorithms/gillespie/src/event_skipping/initialiser/resume.rs index 9f8e10694..dc2797935 100644 --- a/rustcoalescence/algorithms/gillespie/src/event_skipping/initialiser/resume.rs +++ b/rustcoalescence/algorithms/gillespie/src/event_skipping/initialiser/resume.rs @@ -62,13 +62,12 @@ where fn init< 'h, - 'p, T: TrustedOriginSampler<'h, M, Habitat = O::Habitat>, S: GloballyCoherentLineageStore, X: EmigrationExit, I: ImmigrationEntry, Q: Reporter, - P: LocalPartition<'p, Q>, + P: LocalPartition, >( self, origin_sampler: T, diff --git a/rustcoalescence/algorithms/gillespie/src/event_skipping/launch.rs b/rustcoalescence/algorithms/gillespie/src/event_skipping/launch.rs index 8e92f15b0..6a970c982 100644 --- a/rustcoalescence/algorithms/gillespie/src/event_skipping/launch.rs +++ b/rustcoalescence/algorithms/gillespie/src/event_skipping/launch.rs @@ -34,12 +34,11 @@ use crate::arguments::{ #[allow(clippy::shadow_unrelated, clippy::too_many_lines)] pub fn initialise_and_simulate< - 'p, M: MathsCore, G: SplittableRng, O: Scenario, R: Reporter, - P: LocalPartition<'p, R>, + P: LocalPartition, I: Iterator, L: EventSkippingLineageStoreSampleInitialiser, Error, diff --git a/rustcoalescence/algorithms/gillespie/src/event_skipping/mod.rs b/rustcoalescence/algorithms/gillespie/src/event_skipping/mod.rs index b8f68c957..bd9cc8290 100644 --- a/rustcoalescence/algorithms/gillespie/src/event_skipping/mod.rs +++ b/rustcoalescence/algorithms/gillespie/src/event_skipping/mod.rs @@ -53,7 +53,7 @@ where GloballyCoherentLineageStore, O::DispersalSampler: SeparableDispersalSampler, { - type Algorithm<'p, P: LocalPartition<'p, R>> = Self; + type Algorithm> = Self; fn get_logical_partition_size( args: &Self::Arguments, @@ -63,14 +63,8 @@ where } } -impl< - 'p, - O: Scenario, - R: Reporter, - P: LocalPartition<'p, R>, - M: MathsCore, - G: SplittableRng, - > Algorithm<'p, M, G, O, R, P> for EventSkippingAlgorithm +impl, R: Reporter, P: LocalPartition, M: MathsCore, G: SplittableRng> + Algorithm for EventSkippingAlgorithm where O::LineageStore>: GloballyCoherentLineageStore, diff --git a/rustcoalescence/algorithms/gillespie/src/gillespie/classical/initialiser/fixup.rs b/rustcoalescence/algorithms/gillespie/src/gillespie/classical/initialiser/fixup.rs index 1ac923fd0..833e1b2c4 100644 --- a/rustcoalescence/algorithms/gillespie/src/gillespie/classical/initialiser/fixup.rs +++ b/rustcoalescence/algorithms/gillespie/src/gillespie/classical/initialiser/fixup.rs @@ -90,13 +90,12 @@ impl, M: MathsCore, G: RngCore, O: Scena fn init< 'h, - 'p, T: TrustedOriginSampler<'h, M, Habitat = O::Habitat>, S: LocallyCoherentLineageStore, X: EmigrationExit, I: ImmigrationEntry, Q: Reporter, - P: LocalPartition<'p, Q>, + P: LocalPartition, >( self, origin_sampler: T, diff --git a/rustcoalescence/algorithms/gillespie/src/gillespie/classical/initialiser/genesis.rs b/rustcoalescence/algorithms/gillespie/src/gillespie/classical/initialiser/genesis.rs index 4b64fb6e0..51b885937 100644 --- a/rustcoalescence/algorithms/gillespie/src/gillespie/classical/initialiser/genesis.rs +++ b/rustcoalescence/algorithms/gillespie/src/gillespie/classical/initialiser/genesis.rs @@ -37,13 +37,12 @@ impl, O: Scenario> fn init< 'h, - 'p, T: TrustedOriginSampler<'h, M, Habitat = O::Habitat>, S: LocallyCoherentLineageStore, X: EmigrationExit, I: ImmigrationEntry, Q: Reporter, - P: LocalPartition<'p, Q>, + P: LocalPartition, >( self, origin_sampler: T, diff --git a/rustcoalescence/algorithms/gillespie/src/gillespie/classical/initialiser/mod.rs b/rustcoalescence/algorithms/gillespie/src/gillespie/classical/initialiser/mod.rs index 1f2ea44cf..83becf20e 100644 --- a/rustcoalescence/algorithms/gillespie/src/gillespie/classical/initialiser/mod.rs +++ b/rustcoalescence/algorithms/gillespie/src/gillespie/classical/initialiser/mod.rs @@ -59,13 +59,12 @@ pub trait ClassicalLineageStoreSampleInitialiser< #[allow(clippy::type_complexity)] fn init< 'h, - 'p, T: TrustedOriginSampler<'h, M, Habitat = O::Habitat>, S: LocallyCoherentLineageStore, X: EmigrationExit, I: ImmigrationEntry, Q: Reporter, - P: LocalPartition<'p, Q>, + P: LocalPartition, >( self, origin_sampler: T, diff --git a/rustcoalescence/algorithms/gillespie/src/gillespie/classical/initialiser/resume.rs b/rustcoalescence/algorithms/gillespie/src/gillespie/classical/initialiser/resume.rs index 42002b0ba..34b49dda0 100644 --- a/rustcoalescence/algorithms/gillespie/src/gillespie/classical/initialiser/resume.rs +++ b/rustcoalescence/algorithms/gillespie/src/gillespie/classical/initialiser/resume.rs @@ -43,13 +43,12 @@ impl, M: MathsCore, G: RngCore, O: Scena fn init< 'h, - 'p, T: TrustedOriginSampler<'h, M, Habitat = O::Habitat>, S: LocallyCoherentLineageStore, X: EmigrationExit, I: ImmigrationEntry, Q: Reporter, - P: LocalPartition<'p, Q>, + P: LocalPartition, >( self, origin_sampler: T, diff --git a/rustcoalescence/algorithms/gillespie/src/gillespie/classical/launch.rs b/rustcoalescence/algorithms/gillespie/src/gillespie/classical/launch.rs index 750102da6..b53b2882f 100644 --- a/rustcoalescence/algorithms/gillespie/src/gillespie/classical/launch.rs +++ b/rustcoalescence/algorithms/gillespie/src/gillespie/classical/launch.rs @@ -34,12 +34,11 @@ use super::initialiser::ClassicalLineageStoreSampleInitialiser; #[allow(clippy::too_many_lines)] pub fn initialise_and_simulate< - 'p, M: MathsCore, G: SplittableRng, O: Scenario, R: Reporter, - P: LocalPartition<'p, R>, + P: LocalPartition, I: Iterator, L: ClassicalLineageStoreSampleInitialiser, Error, diff --git a/rustcoalescence/algorithms/gillespie/src/gillespie/classical/mod.rs b/rustcoalescence/algorithms/gillespie/src/gillespie/classical/mod.rs index 8fdbd0aa9..691c7af5b 100644 --- a/rustcoalescence/algorithms/gillespie/src/gillespie/classical/mod.rs +++ b/rustcoalescence/algorithms/gillespie/src/gillespie/classical/mod.rs @@ -29,13 +29,12 @@ use initialiser::{ // Optimised 'Classical' implementation for the `UniformTurnoverSampler` impl< - 'p, O: Scenario, R: Reporter, - P: LocalPartition<'p, R>, + P: LocalPartition, M: MathsCore, G: SplittableRng, - > Algorithm<'p, M, G, O, R, P> for GillespieAlgorithm + > Algorithm for GillespieAlgorithm where O::LineageStore>: LocallyCoherentLineageStore, diff --git a/rustcoalescence/algorithms/gillespie/src/gillespie/mod.rs b/rustcoalescence/algorithms/gillespie/src/gillespie/mod.rs index 4a9f6c08c..ed7dcc724 100644 --- a/rustcoalescence/algorithms/gillespie/src/gillespie/mod.rs +++ b/rustcoalescence/algorithms/gillespie/src/gillespie/mod.rs @@ -36,7 +36,7 @@ where O::LineageStore>: LocallyCoherentLineageStore, { - type Algorithm<'p, P: LocalPartition<'p, R>> = Self; + type Algorithm> = Self; fn get_logical_partition_size( args: &Self::Arguments, diff --git a/rustcoalescence/algorithms/gillespie/src/gillespie/turnover/initialiser/fixup.rs b/rustcoalescence/algorithms/gillespie/src/gillespie/turnover/initialiser/fixup.rs index 5483b1567..a2ded2e9f 100644 --- a/rustcoalescence/algorithms/gillespie/src/gillespie/turnover/initialiser/fixup.rs +++ b/rustcoalescence/algorithms/gillespie/src/gillespie/turnover/initialiser/fixup.rs @@ -95,7 +95,6 @@ impl, M: MathsCore, G: RngCore, O: Scena fn init< 'h, - 'p, T: TrustedOriginSampler<'h, M, Habitat = O::Habitat>, S: LocallyCoherentLineageStore, X: EmigrationExit, @@ -113,7 +112,7 @@ impl, M: MathsCore, G: RngCore, O: Scena >, I: ImmigrationEntry, Q: Reporter, - P: LocalPartition<'p, Q>, + P: LocalPartition, >( self, origin_sampler: T, diff --git a/rustcoalescence/algorithms/gillespie/src/gillespie/turnover/initialiser/genesis.rs b/rustcoalescence/algorithms/gillespie/src/gillespie/turnover/initialiser/genesis.rs index 7e111a418..28a29ffae 100644 --- a/rustcoalescence/algorithms/gillespie/src/gillespie/turnover/initialiser/genesis.rs +++ b/rustcoalescence/algorithms/gillespie/src/gillespie/turnover/initialiser/genesis.rs @@ -55,7 +55,6 @@ impl, O: Scenario> fn init< 'h, - 'p, T: TrustedOriginSampler<'h, M, Habitat = O::Habitat>, S: LocallyCoherentLineageStore, X: EmigrationExit, @@ -73,7 +72,7 @@ impl, O: Scenario> >, I: ImmigrationEntry, Q: Reporter, - P: LocalPartition<'p, Q>, + P: LocalPartition, >( self, origin_sampler: T, diff --git a/rustcoalescence/algorithms/gillespie/src/gillespie/turnover/initialiser/mod.rs b/rustcoalescence/algorithms/gillespie/src/gillespie/turnover/initialiser/mod.rs index 4def88e33..767a01580 100644 --- a/rustcoalescence/algorithms/gillespie/src/gillespie/turnover/initialiser/mod.rs +++ b/rustcoalescence/algorithms/gillespie/src/gillespie/turnover/initialiser/mod.rs @@ -47,7 +47,6 @@ pub trait GillespieLineageStoreSampleInitialiser< #[allow(clippy::type_complexity)] fn init< 'h, - 'p, T: TrustedOriginSampler<'h, M, Habitat = O::Habitat>, S: LocallyCoherentLineageStore, X: EmigrationExit, @@ -65,7 +64,7 @@ pub trait GillespieLineageStoreSampleInitialiser< >, I: ImmigrationEntry, Q: Reporter, - P: LocalPartition<'p, Q>, + P: LocalPartition, >( self, origin_sampler: T, diff --git a/rustcoalescence/algorithms/gillespie/src/gillespie/turnover/initialiser/resume.rs b/rustcoalescence/algorithms/gillespie/src/gillespie/turnover/initialiser/resume.rs index 596c69bb2..868fecfa4 100644 --- a/rustcoalescence/algorithms/gillespie/src/gillespie/turnover/initialiser/resume.rs +++ b/rustcoalescence/algorithms/gillespie/src/gillespie/turnover/initialiser/resume.rs @@ -61,7 +61,6 @@ impl, M: MathsCore, G: RngCore, O: Scena fn init< 'h, - 'p, T: TrustedOriginSampler<'h, M, Habitat = O::Habitat>, S: LocallyCoherentLineageStore, X: EmigrationExit, @@ -79,7 +78,7 @@ impl, M: MathsCore, G: RngCore, O: Scena >, I: ImmigrationEntry, Q: Reporter, - P: LocalPartition<'p, Q>, + P: LocalPartition, >( self, origin_sampler: T, diff --git a/rustcoalescence/algorithms/gillespie/src/gillespie/turnover/launch.rs b/rustcoalescence/algorithms/gillespie/src/gillespie/turnover/launch.rs index e34dbe25f..91a49c346 100644 --- a/rustcoalescence/algorithms/gillespie/src/gillespie/turnover/launch.rs +++ b/rustcoalescence/algorithms/gillespie/src/gillespie/turnover/launch.rs @@ -33,12 +33,11 @@ use super::initialiser::GillespieLineageStoreSampleInitialiser; #[allow(clippy::shadow_unrelated, clippy::too_many_lines)] pub fn initialise_and_simulate< - 'p, M: MathsCore, G: SplittableRng, O: Scenario, R: Reporter, - P: LocalPartition<'p, R>, + P: LocalPartition, I: Iterator, L: GillespieLineageStoreSampleInitialiser, Error, diff --git a/rustcoalescence/algorithms/gillespie/src/gillespie/turnover/mod.rs b/rustcoalescence/algorithms/gillespie/src/gillespie/turnover/mod.rs index 4c307d4e7..0741a1e0c 100644 --- a/rustcoalescence/algorithms/gillespie/src/gillespie/turnover/mod.rs +++ b/rustcoalescence/algorithms/gillespie/src/gillespie/turnover/mod.rs @@ -30,14 +30,8 @@ use initialiser::{ }; // Default 'Gillespie' implementation for any turnover sampler -impl< - 'p, - O: Scenario, - R: Reporter, - P: LocalPartition<'p, R>, - M: MathsCore, - G: SplittableRng, - > Algorithm<'p, M, G, O, R, P> for GillespieAlgorithm +impl, R: Reporter, P: LocalPartition, M: MathsCore, G: SplittableRng> + Algorithm for GillespieAlgorithm where O::LineageStore>: LocallyCoherentLineageStore, diff --git a/rustcoalescence/algorithms/independent/src/launch.rs b/rustcoalescence/algorithms/independent/src/launch.rs index bc645a6dd..2eab23e40 100644 --- a/rustcoalescence/algorithms/independent/src/launch.rs +++ b/rustcoalescence/algorithms/independent/src/launch.rs @@ -43,12 +43,11 @@ use crate::{ #[allow(clippy::too_many_lines)] pub fn initialise_and_simulate< - 'p, M: MathsCore, G: PrimeableRng, O: Scenario, R: Reporter, - P: LocalPartition<'p, R>, + P: LocalPartition, I: Iterator, L: IndependentLineageStoreSampleInitialiser, Error, diff --git a/rustcoalescence/algorithms/independent/src/lib.rs b/rustcoalescence/algorithms/independent/src/lib.rs index 026d1f1e5..8a01eef95 100644 --- a/rustcoalescence/algorithms/independent/src/lib.rs +++ b/rustcoalescence/algorithms/independent/src/lib.rs @@ -52,7 +52,7 @@ impl AlgorithmDefaults for IndependentAlgorithm { impl, O: Scenario, R: Reporter> AlgorithmDispatch for IndependentAlgorithm { - type Algorithm<'p, P: LocalPartition<'p, R>> = Self; + type Algorithm> = Self; fn get_logical_partition_size( args: &Self::Arguments, @@ -71,14 +71,8 @@ impl, O: Scenario, R: Reporter> Algorithm } } -impl< - 'p, - O: Scenario, - R: Reporter, - P: LocalPartition<'p, R>, - M: MathsCore, - G: PrimeableRng, - > Algorithm<'p, M, G, O, R, P> for IndependentAlgorithm +impl, R: Reporter, P: LocalPartition, M: MathsCore, G: PrimeableRng> + Algorithm for IndependentAlgorithm { type LineageStore = IndependentLineageStore; diff --git a/rustcoalescence/algorithms/src/lib.rs b/rustcoalescence/algorithms/src/lib.rs index b668ee5e9..114bb9915 100644 --- a/rustcoalescence/algorithms/src/lib.rs +++ b/rustcoalescence/algorithms/src/lib.rs @@ -36,15 +36,7 @@ pub trait AlgorithmDefaults { pub trait AlgorithmDispatch, O: Scenario, R: Reporter>: AlgorithmParamters + AlgorithmDefaults { - type Algorithm<'p, P: LocalPartition<'p, R>>: Algorithm< - 'p, - M, - G, - O, - R, - P, - Arguments = Self::Arguments, - >; + type Algorithm>: Algorithm; fn get_logical_partition_size( args: &Self::Arguments, @@ -53,12 +45,11 @@ pub trait AlgorithmDispatch, O: Scenario, R: R } pub trait Algorithm< - 'p, M: MathsCore, G: RngCore, O: Scenario, R: Reporter, - P: LocalPartition<'p, R>, + P: LocalPartition, >: Sized + AlgorithmParamters + AlgorithmDefaults + AlgorithmDispatch { type LineageStore: LineageStore; diff --git a/rustcoalescence/src/args/config/partitioning.rs b/rustcoalescence/src/args/config/partitioning.rs index 8dbf81ea1..255de80bb 100644 --- a/rustcoalescence/src/args/config/partitioning.rs +++ b/rustcoalescence/src/args/config/partitioning.rs @@ -1,3 +1,10 @@ +use necsim_core::{ + cogs::{MathsCore, RngCore}, + reporter::Reporter, +}; +use necsim_impls_std::event_log::recorder::EventLogRecorder; +use rustcoalescence_algorithms::AlgorithmDispatch; +use rustcoalescence_scenarios::Scenario; use serde::{Deserialize, Serialize}; use necsim_partitioning_core::partition::PartitionSize; @@ -44,6 +51,42 @@ impl Partitioning { ), } } + + pub fn get_logical_partition_size< + M: MathsCore, + G: RngCore, + O: Scenario, + R: Reporter, + A: AlgorithmDispatch, + >( + &self, + algorithm_args: &A::Arguments, + ) -> PartitionSize { + match self { + Partitioning::Monolithic(partitioning) => { + A::get_logical_partition_size(algorithm_args, partitioning) + }, + #[cfg(feature = "mpi-partitioning")] + Partitioning::Mpi(partitioning) => { + A::get_logical_partition_size(algorithm_args, partitioning) + }, + #[cfg(feature = "threads-partitioning")] + Partitioning::Threads(partitioning) => { + A::get_logical_partition_size(algorithm_args, partitioning) + }, + } + } + + pub fn will_report_live(&self, event_log: &Option) -> bool { + // TODO: get this information from the partitioning + match self { + Partitioning::Monolithic(_) => event_log.is_none(), + #[cfg(feature = "mpi-partitioning")] + Partitioning::Mpi(_) => false, + #[cfg(feature = "threads-partitioning")] + Partitioning::Threads(_) => false, + } + } } impl Default for Partitioning { diff --git a/rustcoalescence/src/cli/simulate/dispatch/valid/algorithm_scenario.rs b/rustcoalescence/src/cli/simulate/dispatch/valid/algorithm_scenario.rs index 9054dc695..271d68a5d 100644 --- a/rustcoalescence/src/cli/simulate/dispatch/valid/algorithm_scenario.rs +++ b/rustcoalescence/src/cli/simulate/dispatch/valid/algorithm_scenario.rs @@ -1,7 +1,7 @@ use necsim_core::reporter::Reporter; use necsim_core_bond::{NonNegativeF64, OpenClosedUnitF64 as PositiveUnitF64}; use necsim_impls_std::event_log::recorder::EventLogRecorder; -use necsim_partitioning_core::context::ReporterContext; +use necsim_partitioning_core::reporter::ReporterContext; use rustcoalescence_algorithms::AlgorithmDefaults; diff --git a/rustcoalescence/src/cli/simulate/dispatch/valid/info.rs b/rustcoalescence/src/cli/simulate/dispatch/valid/info.rs index 759a3bf09..d0bad0da5 100644 --- a/rustcoalescence/src/cli/simulate/dispatch/valid/info.rs +++ b/rustcoalescence/src/cli/simulate/dispatch/valid/info.rs @@ -2,36 +2,41 @@ use std::fmt::Write; use anyhow::{Context, Result}; -use rustcoalescence_algorithms::{result::SimulationOutcome, Algorithm}; +use necsim_impls_std::event_log::recorder::EventLogRecorder; +use rustcoalescence_algorithms::{result::SimulationOutcome, AlgorithmDispatch}; use necsim_core::{ cogs::{MathsCore, RngCore}, reporter::{boolean::Boolean, Reporter}, }; use necsim_core_bond::NonNegativeF64; -use necsim_partitioning_core::LocalPartition; +use necsim_partitioning_core::reporter::{FinalisableReporter, ReporterContext}; use rustcoalescence_scenarios::{Scenario, ScenarioCogs}; use crate::args::{ - config::sample::{Sample, SampleMode, SampleModeRestart}, + config::{ + partitioning::Partitioning, + sample::{Sample, SampleMode, SampleModeRestart}, + }, utils::parse::try_print, }; -use super::{super::super::BufferingSimulateArgsBuilder, launch}; +use super::{super::super::BufferingSimulateArgsBuilder, partitioning}; #[allow(dead_code)] -#[allow(clippy::needless_pass_by_value)] +#[allow(clippy::too_many_arguments, clippy::too_many_lines)] pub(super) fn dispatch< - 'p, M: MathsCore, G: RngCore, - A: Algorithm<'p, M, G, O, R, P>, + A: AlgorithmDispatch, O: Scenario, R: Reporter, - P: LocalPartition<'p, R>, + P: ReporterContext, >( - mut local_partition: P, + partitioning: Partitioning, + event_log: Option, + reporter_context: P, sample: Sample, rng: G, @@ -71,36 +76,40 @@ where } info!("{}", resume_pause); - let logical_partition = A::get_logical_partition(&algorithm_args, &local_partition); - if logical_partition.size().get() <= 1 { + let logical_partition_size = + partitioning.get_logical_partition_size::(&algorithm_args); + if logical_partition_size.get() <= 1 { info!("The scenario will be simulated as one monolithic partition."); } else { info!( "The scenario will be simulated across {} logical partitions.", - logical_partition.size() + logical_partition_size ); } - let physical_partition = local_partition.get_partition(); - if physical_partition.size().get() <= 1 { + let physical_partition_size = partitioning.get_size(); + if physical_partition_size.get() <= 1 { info!("The simulation will be run on one processing unit."); } else { info!( "The simulation will be distributed across {} processing units.", - physical_partition.size() + physical_partition_size ); } - if ::ReportSpeciation::VALUE { - if P::IsLive::VALUE { + // TODO: get this information from the partitioning + let will_report_live = partitioning.will_report_live(&event_log); + + if R::ReportSpeciation::VALUE { + if will_report_live { info!("The simulation will report speciation events live."); } else { info!("The simulation will record speciation events."); } } - if ::ReportDispersal::VALUE { - if P::IsLive::VALUE { + if R::ReportDispersal::VALUE { + if will_report_live { info!("The simulation will report dispersal events live."); } else { info!("The simulation will record dispersal events."); @@ -108,19 +117,18 @@ where } } - if ::ReportProgress::VALUE { + if R::ReportProgress::VALUE { info!("The simulation will report progress events live."); } - if !::ReportSpeciation::VALUE - && !::ReportDispersal::VALUE - && !::ReportProgress::VALUE - { + if !R::ReportSpeciation::VALUE && !R::ReportDispersal::VALUE && !R::ReportProgress::VALUE { warn!("The simulation will report no events."); } - let result = launch::simulate::( - &mut local_partition, + let (result, reporter) = partitioning::dispatch::( + partitioning, + event_log, + reporter_context, sample, rng, scenario, @@ -141,7 +149,7 @@ where println!(); } - local_partition.finalise_reporting(); + reporter.finalise(); if log::log_enabled!(log::Level::Info) { println!(); diff --git a/rustcoalescence/src/cli/simulate/dispatch/valid/launch.rs b/rustcoalescence/src/cli/simulate/dispatch/valid/launch.rs index 8b1978ee3..9e30290d2 100644 --- a/rustcoalescence/src/cli/simulate/dispatch/valid/launch.rs +++ b/rustcoalescence/src/cli/simulate/dispatch/valid/launch.rs @@ -15,13 +15,12 @@ use rustcoalescence_scenarios::{Scenario, ScenarioCogs}; use crate::args::config::sample::{Sample, SampleMode, SampleModeRestart, SampleOrigin}; pub(super) fn simulate< - 'p, M: MathsCore, G: RngCore, - A: Algorithm<'p, M, G, O, R, P>, + A: Algorithm, O: Scenario, R: Reporter, - P: LocalPartition<'p, R>, + P: LocalPartition, >( local_partition: &mut P, diff --git a/rustcoalescence/src/cli/simulate/dispatch/valid/partitioning.rs b/rustcoalescence/src/cli/simulate/dispatch/valid/partitioning.rs index 6df91cc35..d4a13c0c1 100644 --- a/rustcoalescence/src/cli/simulate/dispatch/valid/partitioning.rs +++ b/rustcoalescence/src/cli/simulate/dispatch/valid/partitioning.rs @@ -4,7 +4,7 @@ use necsim_core::{ }; use necsim_core_bond::NonNegativeF64; use necsim_impls_std::event_log::recorder::EventLogRecorder; -use necsim_partitioning_core::{context::ReporterContext, LocalPartition, Partitioning as _}; +use necsim_partitioning_core::{reporter::ReporterContext, LocalPartition, Partitioning as _}; use necsim_partitioning_monolithic::MonolithicLocalPartition; #[cfg(feature = "mpi-partitioning")] @@ -12,9 +12,12 @@ use necsim_partitioning_mpi::MpiLocalPartition; use rustcoalescence_algorithms::{result::SimulationOutcome, Algorithm, AlgorithmDispatch}; use rustcoalescence_scenarios::{Scenario, ScenarioCogs}; -use crate::args::config::{partitioning::Partitioning, sample::Sample}; +use crate::{ + args::config::{partitioning::Partitioning, sample::Sample}, + reporter::FinalisablePartitioningReporter, +}; -use super::{super::super::BufferingSimulateArgsBuilder, info}; +use super::launch; #[allow(clippy::too_many_arguments)] pub(super) fn dispatch< @@ -34,140 +37,127 @@ pub(super) fn dispatch< scenario: ScenarioCogs, algorithm_args: A::Arguments, pause_before: Option, - - normalised_args: &BufferingSimulateArgsBuilder, -) -> anyhow::Result> +) -> anyhow::Result<(SimulationOutcome, FinalisablePartitioningReporter)> where Result, A::Error>: anyhow::Context, A::Error>, { - let args = ( - sample, - rng, - scenario, - algorithm_args, - pause_before, - normalised_args, - ); + let args = (sample, rng, scenario, algorithm_args, pause_before); // Initialise the local partition and the simulation match partitioning { - Partitioning::Monolithic(partitioning) => partitioning.with_local_partition( - reporter_context, - event_log, - args, - |partition, (sample, rng, scenario, algorithm_args, pause_before, normalised_args)| { - match partition { + Partitioning::Monolithic(partitioning) => partitioning + .with_local_partition( + reporter_context, + event_log, + args, + |partition, (sample, rng, scenario, algorithm_args, pause_before)| match partition { MonolithicLocalPartition::Live(partition) => { - wrap::, O, R, _>( - *partition, + wrap::, O, R, _>( + &mut **partition, sample, rng, scenario, algorithm_args, pause_before, - normalised_args, ) }, MonolithicLocalPartition::Recorded(partition) => { - wrap::, O, R, _>( - *partition, + wrap::, O, R, _>( + &mut **partition, sample, rng, scenario, algorithm_args, pause_before, - normalised_args, ) }, - } - }, - fold, - ), + }, + fold, + ) + .map(|(result, reporter)| { + ( + result, + FinalisablePartitioningReporter::Monolithic(reporter), + ) + }), #[cfg(feature = "mpi-partitioning")] - Partitioning::Mpi(partitioning) => partitioning.with_local_partition( - reporter_context, - event_log, - args, - |partition, (sample, rng, scenario, algorithm_args, pause_before, normalised_args)| { - match partition { - MpiLocalPartition::Root(partition) => { - wrap::, O, R, _>( - *partition, - sample, - rng, - scenario, - algorithm_args, - pause_before, - normalised_args, - ) - }, + Partitioning::Mpi(partitioning) => partitioning + .with_local_partition( + reporter_context, + event_log, + args, + |partition, (sample, rng, scenario, algorithm_args, pause_before)| match partition { + MpiLocalPartition::Root(partition) => wrap::, O, R, _>( + &mut **partition, + sample, + rng, + scenario, + algorithm_args, + pause_before, + ), MpiLocalPartition::Parallel(partition) => { - wrap::, O, R, _>( - *partition, + wrap::, O, R, _>( + &mut **partition, sample, rng, scenario, algorithm_args, pause_before, - normalised_args, ) }, - } - }, - fold, - ), + }, + fold, + ) + .map(|(result, reporter)| (result, FinalisablePartitioningReporter::Mpi(reporter))), #[cfg(feature = "threads-partitioning")] - Partitioning::Threads(partitioning) => partitioning.with_local_partition( - reporter_context, - event_log, - args, - |partition, (sample, rng, scenario, algorithm_args, pause_before, normalised_args)| { - wrap::, O, R, _>( - partition, - sample, - rng, - scenario, - algorithm_args, - pause_before, - normalised_args, - ) - }, - fold, - ), + Partitioning::Threads(partitioning) => partitioning + .with_local_partition( + reporter_context, + event_log, + args, + |partition, (sample, rng, scenario, algorithm_args, pause_before)| { + wrap::, O, R, _>( + partition, + sample, + rng, + scenario, + algorithm_args, + pause_before, + ) + }, + fold, + ) + .map(|(result, reporter)| (result, FinalisablePartitioningReporter::Threads(reporter))), } - .and_then(|result| result.map_err(anyhow::Error::msg)) + .and_then(|(result, reporter)| Ok((result.map_err(anyhow::Error::msg)?, reporter))) } fn wrap< - 'p, M: MathsCore, G: RngCore, - A: Algorithm<'p, M, G, O, R, P>, + A: Algorithm, O: Scenario, R: Reporter, - P: LocalPartition<'p, R>, + P: LocalPartition, >( - local_partition: P, + local_partition: &mut P, sample: Sample, rng: G, scenario: ScenarioCogs, algorithm_args: A::Arguments, pause_before: Option, - - normalised_args: &BufferingSimulateArgsBuilder, ) -> Result, String> where Result, A::Error>: anyhow::Context, A::Error>, { - info::dispatch::, O, R, _>( + launch::simulate::, O, R, _>( local_partition, sample, rng, scenario, algorithm_args, pause_before, - normalised_args, ) .map_err(|err| format!("{err:?}")) } diff --git a/rustcoalescence/src/cli/simulate/dispatch/valid/rng.rs b/rustcoalescence/src/cli/simulate/dispatch/valid/rng.rs index e301bceda..4b7613c27 100644 --- a/rustcoalescence/src/cli/simulate/dispatch/valid/rng.rs +++ b/rustcoalescence/src/cli/simulate/dispatch/valid/rng.rs @@ -1,5 +1,5 @@ use necsim_impls_std::event_log::recorder::EventLogRecorder; -use necsim_partitioning_core::context::ReporterContext; +use necsim_partitioning_core::reporter::ReporterContext; use tiny_keccak::{Hasher, Keccak}; use rustcoalescence_algorithms::{ @@ -25,7 +25,7 @@ use crate::{ use super::{ super::super::{BufferingSimulateArgsBuilder, SimulationOutcome}, - partitioning, + info, }; #[allow(clippy::too_many_arguments)] @@ -55,19 +55,7 @@ where let rng: G = match parse::rng::parse_and_normalise( ron_args, normalised_args, - match &partitioning { - Partitioning::Monolithic(partitioning) => { - A::get_logical_partition_size(&algorithm_args, partitioning) - }, - #[cfg(feature = "mpi-partitioning")] - Partitioning::Mpi(partitioning) => { - A::get_logical_partition_size(&algorithm_args, partitioning) - }, - #[cfg(feature = "threads-partitioning")] - Partitioning::Threads(partitioning) => { - A::get_logical_partition_size(&algorithm_args, partitioning) - }, - }, + partitioning.get_logical_partition_size::(&algorithm_args), )? { RngArgs::Seed(seed) => SeedableRng::seed_from_u64(seed), RngArgs::Sponge(bytes) => { @@ -82,7 +70,7 @@ where RngArgs::State(state) => state.into(), }; - let result = partitioning::dispatch::( + let result = info::dispatch::( partitioning, event_log, reporter_context, diff --git a/rustcoalescence/src/reporter.rs b/rustcoalescence/src/reporter.rs index 98e6de2b1..18ec85758 100644 --- a/rustcoalescence/src/reporter.rs +++ b/rustcoalescence/src/reporter.rs @@ -2,7 +2,7 @@ use std::fmt; use necsim_core::reporter::{boolean::Boolean, FilteredReporter, Reporter}; -use necsim_partitioning_core::context::ReporterContext; +use necsim_partitioning_core::reporter::{FinalisableReporter, ReporterContext}; use necsim_plugins_core::import::ReporterPluginVec; @@ -54,3 +54,24 @@ impl { + Monolithic(::FinalisableReporter), + #[cfg(feature = "mpi-partitioning")] + Mpi(::FinalisableReporter), + #[cfg(feature = "threads-partitioning")] + Threads(::FinalisableReporter), +} + +impl FinalisableReporter for FinalisablePartitioningReporter { + fn finalise(self) { + match self { + Self::Monolithic(reporter) => reporter.finalise(), + #[cfg(feature = "mpi-partitioning")] + Self::Mpi(reporter) => reporter.finalise(), + #[cfg(feature = "threads-partitioning")] + Self::Threads(reporter) => reporter.finalise(), + } + } +}