|
|
@ -5,6 +5,9 @@
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
use ocl::ProQue;
|
|
|
|
use ocl::ProQue;
|
|
|
|
|
|
|
|
use parking_lot::Mutex;
|
|
|
|
|
|
|
|
use std::sync::Arc;
|
|
|
|
|
|
|
|
use std::time::Instant;
|
|
|
|
|
|
|
|
|
|
|
|
pub struct KernelController {
|
|
|
|
pub struct KernelController {
|
|
|
|
pro_que: ProQue,
|
|
|
|
pro_que: ProQue,
|
|
|
@ -20,10 +23,15 @@ impl KernelController {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
pub fn filter_primes(&self, input: Vec<i64>) -> ocl::Result<Vec<i64>> {
|
|
|
|
pub fn filter_primes(&self, input: Vec<i64>) -> ocl::Result<Vec<i64>> {
|
|
|
|
lazy_static::lazy_static! {static ref PRIMES: Vec<i32> = get_lower_primes();}
|
|
|
|
lazy_static::lazy_static! {static ref PRIME_CACHE: Arc<Mutex<Vec<i64>>> = Arc::new(Mutex::new(get_lower_primes(2048)));}
|
|
|
|
|
|
|
|
|
|
|
|
let prime_buffer = self.pro_que.buffer_builder().len(PRIMES.len()).build()?;
|
|
|
|
let prime_buffer = self
|
|
|
|
prime_buffer.write(&PRIMES[..]).enq()?;
|
|
|
|
.pro_que
|
|
|
|
|
|
|
|
.buffer_builder()
|
|
|
|
|
|
|
|
.len(PRIME_CACHE.lock().len())
|
|
|
|
|
|
|
|
.build()?;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
prime_buffer.write(&PRIME_CACHE.lock()[..]).enq()?;
|
|
|
|
|
|
|
|
|
|
|
|
let input_buffer = self.pro_que.buffer_builder().len(input.len()).build()?;
|
|
|
|
let input_buffer = self.pro_que.buffer_builder().len(input.len()).build()?;
|
|
|
|
input_buffer.write(&input[..]).enq()?;
|
|
|
|
input_buffer.write(&input[..]).enq()?;
|
|
|
@ -55,27 +63,43 @@ impl KernelController {
|
|
|
|
let mut input_o = vec![0i64; input_buffer.len()];
|
|
|
|
let mut input_o = vec![0i64; input_buffer.len()];
|
|
|
|
input_buffer.read(&mut input_o).enq()?;
|
|
|
|
input_buffer.read(&mut input_o).enq()?;
|
|
|
|
|
|
|
|
|
|
|
|
Ok(input
|
|
|
|
let primes = input
|
|
|
|
.iter()
|
|
|
|
.iter()
|
|
|
|
.enumerate()
|
|
|
|
.enumerate()
|
|
|
|
.filter(|(index, _)| output[*index] == 1)
|
|
|
|
.filter(|(index, _)| output[*index] == 1)
|
|
|
|
.map(|(_, v)| *v)
|
|
|
|
.map(|(_, v)| *v)
|
|
|
|
.collect())
|
|
|
|
.collect::<Vec<i64>>();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let start = Instant::now();
|
|
|
|
|
|
|
|
let mut prime_cache = PRIME_CACHE.lock();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if prime_cache.len() < 1024 * 1024 * 1024 {
|
|
|
|
|
|
|
|
prime_cache.append(&mut primes.clone());
|
|
|
|
|
|
|
|
prime_cache.sort();
|
|
|
|
|
|
|
|
prime_cache.dedup();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
println!(
|
|
|
|
|
|
|
|
"Prime caching took: {} ms, size: {}",
|
|
|
|
|
|
|
|
start.elapsed().as_secs_f64() * 1000f64,
|
|
|
|
|
|
|
|
prime_cache.len(),
|
|
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Ok(primes)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// Returns a list of prime numbers that can be used to speed up the divisibility check
|
|
|
|
/// Returns a list of prime numbers that can be used to speed up the divisibility check
|
|
|
|
fn get_lower_primes() -> Vec<i32> {
|
|
|
|
fn get_lower_primes(count: usize) -> Vec<i64> {
|
|
|
|
let mut primes = Vec::new();
|
|
|
|
let mut primes = Vec::new();
|
|
|
|
let mut num = 3;
|
|
|
|
let mut num = 3;
|
|
|
|
|
|
|
|
|
|
|
|
while primes.len() < 1024 {
|
|
|
|
while primes.len() < count {
|
|
|
|
let mut is_prime = true;
|
|
|
|
let mut is_prime = true;
|
|
|
|
|
|
|
|
|
|
|
|
if num < 3 || num % 2 == 0 {
|
|
|
|
if num < 3 || num % 2 == 0 {
|
|
|
|
is_prime = false;
|
|
|
|
is_prime = false;
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
for i in (3..((num as f32).sqrt().ceil() as i32)).step_by(2) {
|
|
|
|
for i in (3..((num as f64).sqrt().ceil() as i64)).step_by(2) {
|
|
|
|
if num % i == 0 {
|
|
|
|
if num % i == 0 {
|
|
|
|
is_prime = false;
|
|
|
|
is_prime = false;
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|