3
\$\begingroup\$

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)
 }
 }
}
Jamal
35.2k13 gold badges134 silver badges238 bronze badges
asked Dec 3, 2014 at 21:05
\$\endgroup\$

1 Answer 1

2
\$\begingroup\$

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:

  1. Removing Unfold, as it isn't stable in the 1.0 beta.
  2. Using thread::scoped instead of a Future.
  3. Using i64 instead of int

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.

answered Apr 5, 2015 at 22:35
\$\endgroup\$
3
  • \$\begingroup\$ The original code ran already, at least back when I asked that question. It was in December, after all. \$\endgroup\$ Commented 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\$ Commented 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\$ Commented Apr 6, 2015 at 5:19

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.