If there's a better place to ask this please close and direct me there but this seems like it is a lack of Documentation or a bug. It could simply be that Rayon's parallelism model is not the right one for my task.
My main problem is that iter_par seems to start up with NCPU threads (16) and then eventually
backs off to 3-4 at a time while the rest just sleep. The same functionality in (quite complex) shell runs in 190 seconds, but 250 seconds in rust (--release). The code being ran in parallel is very expensive since it does a fork+exec.
I've tried .with_max_len(1) and other combinations like using std::usize::MAX but nothing seems to help.
What I was looking for was a way to have a shared work queue that keeps all threads busy, sending work to the next available thread rather than splitting the work up "evenly". That already sounds like it's not what Rayon is intended for, but with the work stealing feature I figured it should be a decent library for prototyping, but was surprised by the results.
Details
I'm also on day 3 of learning Rust.
Using rayon 1.0.0.
let mut portvars: FnvHashMap<&String, FnvHashMap<String, String>> =
FnvHashMap::with_capacity_and_hasher(ports.len(), Default::default());
portvars.par_extend(ports.par_iter().with_max_len(1).map(|port|
(port, port_var_fetch(&config, port, &fetchvars))
));
Here ports is a Vec<String> with 26000 items. I have 16 CPU.
port_var_fetch runs make to gather variables from Makefiles (on FreeBSD make -V can be used for this, I'm not sure what the equivalent in gmake is).
port_var_fetch
I've listed the port_var_fetch in case its implementation is relevant.
This is the fetchvars variable that is passed in.
let mut fetchvars = Vec::new();
fetchvars.push(("PKGNAME", "PKGNAME"));
fetchvars.push(("MAINTAINER", "MAINTAINER"));
fetchvars.push(("FLAVORS", "FLAVORS"));
fetchvars.push(("FLAVOR", "FLAVOR"));
fetchvars.push(("CATEGORIES", "CATEGORIES"));
fetchvars.push(("IGNORE", "IGNORE"));
fetchvars.push(("DEPEND_SPECIALS", "${_DEPEND_SPECIALS:C,^${PORTSDIR}/,,}"));
fetchvars.push(("SELECTED_OPTIONS", "SELECTED_OPTIONS:O"));
fetchvars.push(("LIB_DEPENDS", "LIB_DEPENDS"));
fetchvars.push(("RUN_DEPENDS", "RUN_DEPENDS"));
fn port_var_fetch(config: &HashMap<String, String>,
port: &str, vars: &Vec<(&str, &str)>) -> FnvHashMap<String, String> {
let mut args = Vec::with_capacity(vars.len() * 2);
for var in vars {
args.push("-V");
args.push(var.1);
}
let results = pmake(&config, port, args);
let mut result: FnvHashMap<String, String> =
FnvHashMap::with_capacity_and_hasher(vars.len(), Default::default());
result.extend(vars.into_iter().zip(results.lines())
.map(|(var, value)| ((*var).0.into(), value.into())));
result
}
fn pmake(config: &HashMap<String, String>,
origin: &str, args: Vec<&str>) -> String {
make(&(config.get("PORTSDIR").unwrap().to_string() + "/" + origin), args)
}
fn make(dir: &str, args: Vec<&str>) -> String {
let mut cmd = Command::new("/usr/bin/make");
cmd.stdin(Stdio::inherit())
.stderr(Stdio::inherit())
.arg("-C").arg(dir)
.args(args);
let output = cmd.output().expect("Make failed");
String::from_utf8_lossy(&output.stdout).trim().to_string()
}
If there's a better place to ask this please close and direct me there but this seems like it is a lack of Documentation or a bug. It could simply be that Rayon's parallelism model is not the right one for my task.
My main problem is that
iter_parseems to start up with NCPU threads (16) and then eventuallybacks off to 3-4 at a time while the rest just sleep. The same functionality in (quite complex) shell runs in 190 seconds, but 250 seconds in rust (--release). The code being ran in parallel is very expensive since it does a fork+exec.
I've tried
.with_max_len(1)and other combinations like usingstd::usize::MAXbut nothing seems to help.What I was looking for was a way to have a shared work queue that keeps all threads busy, sending work to the next available thread rather than splitting the work up "evenly". That already sounds like it's not what Rayon is intended for, but with the work stealing feature I figured it should be a decent library for prototyping, but was surprised by the results.
Details
I'm also on day 3 of learning Rust.
Using rayon 1.0.0.
Here
portsis aVec<String>with 26000 items. I have 16 CPU.port_var_fetchrunsmaketo gather variables from Makefiles (on FreeBSDmake -Vcan be used for this, I'm not sure what the equivalent ingmakeis).port_var_fetch
I've listed the
port_var_fetchin case its implementation is relevant.This is the
fetchvarsvariable that is passed in.