diff --git a/src/kernel_controller/kernel.cl b/src/kernel_controller/kernel.cl index 8300507..053579d 100644 --- a/src/kernel_controller/kernel.cl +++ b/src/kernel_controller/kernel.cl @@ -5,40 +5,41 @@ */ -__kernel void check_prime(const uint LOWER_PRIME_COUNT, __global const ulong *LOWER_PRIMES, __global const ulong *IN, __global bool *OUT) { +__kernel void check_prime_cached(const uint LOWER_PRIME_COUNT, __global const ulong *LOWER_PRIMES, __global const ulong *IN, __global bool *OUT) { uint id = get_global_id(0); ulong num = IN[id]; - bool prime = true; ulong limit = (ulong) native_sqrt((double) num) + 1; if (num < 3 || num % 2 == 0) { - prime = false; + return; } else { for (uint i = 0; i < LOWER_PRIME_COUNT; i++) { if (LOWER_PRIMES[i] >= limit) { break; } if (num % LOWER_PRIMES[i] == 0) { - prime = false; - break; + return; } } - ulong start = LOWER_PRIMES[LOWER_PRIME_COUNT - 1]; + } - if (prime && start < limit) { - start -= start % 3; + OUT[id] = true; +} - if (start % 2 == 0) { - start -= 3; - } - for (ulong i = start; i <= limit; i += 6) { - if (num % (i - 2) == 0 || num % (i - 4) == 0) { - prime = false; - break; - } +__kernel void check_prime(__global const ulong *IN, __global bool *OUT) { + uint id = get_global_id(0); + ulong num = IN[id]; + ulong limit = (ulong) native_sqrt((double) num) + 1; + + if (num < 3 || num % 2 == 0) { + return; + } else { + for (ulong i = 9; i <= limit; i += 6) { + if (num % (i - 2) == 0 || num % (i - 4) == 0) { + return; } } } - OUT[id] = prime; + OUT[id] = true; } \ No newline at end of file diff --git a/src/kernel_controller/mod.rs b/src/kernel_controller/mod.rs index 1781292..fdd9ab6 100644 --- a/src/kernel_controller/mod.rs +++ b/src/kernel_controller/mod.rs @@ -46,7 +46,12 @@ impl KernelController { } pub fn filter_primes(&self, input: Vec) -> ocl::Result> { - lazy_static::lazy_static! {static ref PRIME_CACHE: Arc>> = Arc::new(Mutex::new(get_primes(2048)));} + lazy_static::lazy_static! {static ref PRIME_CACHE: Arc>> = Arc::new(Mutex::new(Vec::new()));} + if PRIME_CACHE.lock().len() == 0 { + PRIME_CACHE.lock().append(&mut get_primes( + (*input.iter().max().unwrap_or(&1024) as f64).sqrt().ceil() as u64, + )); + } let prime_buffer = self .pro_que @@ -68,7 +73,7 @@ impl KernelController { let kernel = self .pro_que - .kernel_builder("check_prime") + .kernel_builder("check_prime_cached") .arg(prime_buffer.len() as u32) .arg(&prime_buffer) .arg(&input_buffer) @@ -120,15 +125,17 @@ impl KernelController { } /// Returns a list of prime numbers that can be used to speed up the divisibility check -fn get_primes(count: usize) -> Vec { +fn get_primes(max_number: u64) -> Vec { let start = Instant::now(); - let mut primes = Vec::with_capacity(count); + let mut primes = Vec::with_capacity((max_number as f64).sqrt() as usize); let mut num = 3; - while primes.len() < count { + while num < max_number { let mut is_prime = true; - if num < 3 || num % 2 == 0 { + if num == 2 { + is_prime = true; + } else if num < 3 || num % 2 == 0 { is_prime = false; } else { let check_stop = (num as f64).sqrt().ceil() as u64; @@ -162,7 +169,7 @@ fn get_primes(count: usize) -> Vec { } println!( "Generated {} primes on the cpu in {} ms", - count, + primes.len(), start.elapsed().as_secs_f64() * 1000f64 ); diff --git a/src/main.rs b/src/main.rs index 66965ea..09585f3 100644 --- a/src/main.rs +++ b/src/main.rs @@ -78,6 +78,7 @@ fn calculate_primes(prime_opts: CalculatePrimes, controller: KernelController) - if offset % 2 == 0 { offset += 1; } + sender.send(vec![2]).unwrap(); loop { let start = Instant::now(); let numbers = (offset..(prime_opts.numbers_per_step as u64 * 2 + offset))