Skip to content

Commit

Permalink
disable multithreading using rayon for wasm32 targets
Browse files Browse the repository at this point in the history
  • Loading branch information
haraldmaida committed Nov 7, 2021
1 parent b476229 commit bfc47f9
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 2 deletions.
4 changes: 3 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,12 @@ wasm-bindgen = ["wasm-bindgen_", "chrono/wasmbind"]
chrono = "0.4"
rand = { version = "0.8", default-features = false, features = ["getrandom"] }
rand_xoshiro = "0.6"
rayon = "1"
fixedbitset = { version = "0.4", optional = true }
smallvec = { version = "1", optional = true }

[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
rayon = "1"

[target.'cfg(all(target_arch = "wasm32", not(any(target_os = "emscripten", target_os = "wasi"))))'.dependencies]
wasm-bindgen_ = { version = "0.2", package = "wasm-bindgen", optional = true }
getrandom = { version = "0.2", features = ["js"] }
Expand Down
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,8 @@ genevo = "0.7"
* `Smallvec`: provides `Smallvec` to be used as genotype

since version 0.7.0 `genevo` supports wasm targets. To use `genevo` for target
`wasm32-unknown-unknown` enable the crate feature `wasm-bindgen`.
`wasm32-unknown-unknown` enable the crate feature `wasm-bindgen`. Note: on wasm32 targets
multithreading (implemented using `rayon`) is disabled!

```toml
[dependencies]
Expand Down
55 changes: 55 additions & 0 deletions src/ga/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ use crate::{
statistic::{timed, ProcessingTime, TimedResult, TrackProcessingTime},
};
use chrono::Local;
#[cfg(not(target_arch = "wasm32"))]
use rayon;
use std::{
fmt::{self, Display},
Expand Down Expand Up @@ -256,6 +257,7 @@ where

/// Calculates the `genetic::Fitness` value of each `genetic::Genotype` and
/// records the highest and lowest values.
#[cfg(not(target_arch = "wasm32"))]
fn par_evaluate_fitness<G, F, E>(population: &[G], evaluator: &E) -> TimedResult<(Vec<F>, F, F)>
where
G: Genotype + Sync,
Expand Down Expand Up @@ -307,6 +309,32 @@ where
}
}

#[cfg(target_arch = "wasm32")]
fn par_evaluate_fitness<G, F, E>(population: &[G], evaluator: &E) -> TimedResult<(Vec<F>, F, F)>
where
G: Genotype + Sync,
F: Fitness + Send + Sync,
E: FitnessFunction<G, F> + Sync,
{
timed(|| {
let mut fitness = Vec::with_capacity(population.len());
let mut highest = evaluator.lowest_possible_fitness();
let mut lowest = evaluator.highest_possible_fitness();
for genome in population.iter() {
let score = evaluator.fitness_of(genome);
if score > highest {
highest = score.clone();
}
if score < lowest {
lowest = score.clone();
}
fitness.push(score);
}
(fitness, highest, lowest)
})
.run()
}

/// Determines the best solution of the current population
fn determine_best_solution<G, F>(
generation: u64,
Expand Down Expand Up @@ -336,6 +364,7 @@ where

/// Lets the parents breed their offspring and mutate its children. And
/// finally combines the offspring of all parents into one big offspring.
#[cfg(not(target_arch = "wasm32"))]
fn par_breed_offspring<G, C, M>(
parents: Vec<Parents<G>>,
breeder: &C,
Expand Down Expand Up @@ -382,3 +411,29 @@ where
}
}
}

#[cfg(target_arch = "wasm32")]
fn par_breed_offspring<G, C, M>(
parents: Vec<Parents<G>>,
breeder: &C,
mutator: &M,
rng: &mut Prng,
) -> TimedResult<Offspring<G>>
where
G: Genotype + Send,
C: CrossoverOp<G> + Sync,
M: MutationOp<G> + Sync,
{
timed(|| {
let mut offspring: Offspring<G> = Vec::with_capacity(parents.len() * parents[0].len());
for parents in parents {
let children = breeder.crossover(parents, rng);
for child in children {
let mutated = mutator.mutate(child, rng);
offspring.push(mutated);
}
}
offspring
})
.run()
}
17 changes: 17 additions & 0 deletions src/population/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ use crate::{
random::{get_rng, random_seed, Prng, Rng, Seed},
};
use rand::distributions::uniform::SampleUniform;
#[cfg(not(target_arch = "wasm32"))]
use rayon;
use std::{fmt::Debug, marker::PhantomData};

Expand Down Expand Up @@ -148,6 +149,7 @@ where
#[derive(Clone, Debug, PartialEq)]
pub struct PopulationBuilder;

#[cfg(not(target_arch = "wasm32"))]
impl PopulationBuilder {
fn build_population<B, G>(genome_builder: &B, size: usize, mut rng: Prng) -> Population<G>
where
Expand Down Expand Up @@ -179,6 +181,21 @@ impl PopulationBuilder {
}
}

#[cfg(target_arch = "wasm32")]
impl PopulationBuilder {
fn build_population<B, G>(genome_builder: &B, size: usize, mut rng: Prng) -> Population<G>
where
B: GenomeBuilder<G>,
G: Genotype,
{
Population {
individuals: (0..size)
.map(|index| genome_builder.build_genome(index, &mut rng))
.collect(),
}
}
}

/// A `GenomeBuilder` defines how to build individuals of a population for
/// custom `genetic::Genotype`s.
///
Expand Down

0 comments on commit bfc47f9

Please sign in to comment.