Linq's AsParallel()
call would be my normal way of doing something like this, but Rust hasn't stolen that just yet. This method has obvious shortcomings, but I'm still sort of hoping for it to shave off a little time by engaging a second core.
How can I achieve this less terribly?
use std::num::Float;
use std::sync::Future;
fn main() {
// This implementation cheats because it knows the biggest prime value
// in the range: 7919. Getting primes in parallel is a pain in the ass
// pretty much no matter what, and it's probably not worth it, but on
// the up side... Eh. Whatever. Only other way I know to do this would
// be to get the first *1001* primes, sort them, and then fold the first
// thousand after stuffing them into a vector.
let mut path_1 = Future::spawn(proc() {
Unfold::new(3, incr).filter(prime).take_while(|n| *n <= 7919).fold(0i, |a, b| a + b)
});
let mut path_2 = Future::spawn(proc() {
Unfold::new(5, incr).filter(prime).take_while(|n| *n <= 7919).fold(0i, |a, b| a + b)
});
// As you can see, my plan here was to get 999 primes (skipping 2)
// and then add 2 back in later on.
println!("{}", path_1.get() + path_2.get() + 2);
}
fn incr(n: &mut int) -> Option<int> {
let r = Some(*n);
*n = *n + 4;
r
}
fn prime(n: &int) -> bool {
match n {
&1 => false,
&2 => true,
&3 => true,
n if *n % 2 == 0 => false,
_ => {
let max = (*n as f64).sqrt() as int + 1;
!range(2, max).any(|i| *n % i == 0)
}
}
}
1 Answer 1
It isn't clear to me what you are asking. However, I was able to update your code and run it:
use std::thread;
struct PrimeIncrement(i64);
impl Iterator for PrimeIncrement {
type Item = i64;
fn next(&mut self) -> Option<i64> {
self.0 += 4; // What do you mean "integer overflow"? ^_^
Some(self.0)
}
}
fn main() {
let path_1 = thread::scoped(|| {
PrimeIncrement(3).filter(prime).take_while(|&n| n <= 7919).fold(0, |a, b| a + b)
});
let path_2 = thread::scoped(|| {
PrimeIncrement(5).filter(prime).take_while(|&n| n <= 7919).fold(0, |a, b| a + b)
});
let a = path_1.join();
let b = path_2.join();
println!("{}", 2 + a + b);
}
fn prime(n: &i64) -> bool {
match n {
&1 => false,
&2 => true,
&3 => true,
n if *n % 2 == 0 => false,
_ => {
let max = (*n as f64).sqrt() as i64 + 1;
!(2..max).any(|i| *n % i == 0)
}
}
}
The main changes were:
- Removing
Unfold
, as it isn't stable in the 1.0 beta. - Using
thread::scoped
instead of aFuture
. - Using
i64
instead ofint
Update for Rust 1.3
The thread::scoped
API was found to have soundness problems and has been deprecated. In this case, thread::spawn
is powerful enough, so I've replaced that:
use std::thread;
struct PrimeIncrement(i64);
impl Iterator for PrimeIncrement {
type Item = i64;
fn next(&mut self) -> Option<i64> {
self.0 += 4; // What do you mean "integer overflow"? ^_^
Some(self.0)
}
}
fn main() {
let path_1 = thread::spawn(|| {
PrimeIncrement(3).filter(prime).take_while(|&n| n <= 7919).fold(0, |a, b| a + b)
});
let path_2 = thread::spawn(|| {
PrimeIncrement(5).filter(prime).take_while(|&n| n <= 7919).fold(0, |a, b| a + b)
});
let a = path_1.join().unwrap();
let b = path_2.join().unwrap();
println!("{}", 2 + a + b);
}
fn prime(n: &i64) -> bool {
match *n {
1 => false,
2 => true,
3 => true,
n if n % 2 == 0 => false,
n => {
let max = (n as f64).sqrt() as i64 + 1;
!(2..max).any(|i| n % i == 0)
}
}
}
Additionally, I now match on *n
, which avoids the need to have quite as many dereferences.
-
\$\begingroup\$ The original code ran already, at least back when I asked that question. It was in December, after all. \$\endgroup\$archer884– archer8842015年04月06日 02:07:00 +00:00Commented Apr 6, 2015 at 2:07
-
\$\begingroup\$ @archer884 maybe you can clarify your question - I still don't know what you would like to get from a code review. \$\endgroup\$Shepmaster– Shepmaster2015年04月06日 02:08:59 +00:00Commented Apr 6, 2015 at 2:08
-
\$\begingroup\$ I asked for a cleaner way to distribute work across several cores. The short answer is that Rust doesn't currently have a clean, easy way to do that. I realize that now, but I was not aware of that back in December of 2014. \$\endgroup\$archer884– archer8842015年04月06日 05:19:39 +00:00Commented Apr 6, 2015 at 5:19