a deliberately stupid space heater that wastes electricity on fire shaders and prime numbers
at main 62 lines 1.8 kB view raw
1use std::sync::atomic::{AtomicBool, AtomicU64, Ordering}; 2use std::sync::Arc; 3 4/// Test whether `n` is prime using trial division up to √n. 5/// Deliberately not optimized — we *want* to burn CPU. 6fn is_prime(n: u64) -> bool { 7 if n < 2 { 8 return false; 9 } 10 if n < 4 { 11 return true; 12 } 13 if n % 2 == 0 || n % 3 == 0 { 14 return false; 15 } 16 let mut i = 5u64; 17 while i.saturating_mul(i) <= n { 18 if n % i == 0 || n % (i + 2) == 0 { 19 return false; 20 } 21 i += 6; 22 } 23 true 24} 25 26/// CPU-burning worker that counts primes by brute-force trial division. 27/// 28/// Each thread tests a disjoint slice of odd numbers (interleaved by stride) 29/// and atomically increments shared counters for primes found and numbers tested. 30/// Uses constant memory regardless of how long it runs. 31pub fn prime_worker( 32 running: Arc<AtomicBool>, 33 primes_found: Arc<AtomicU64>, 34 numbers_tested: Arc<AtomicU64>, 35 thread_id: u64, 36 num_threads: u64, 37) { 38 // Each thread works on odd numbers: 3 + 2*thread_id, stepping by 2*num_threads. 39 // Thread 0 also accounts for the prime 2 by adding 1 to its first batch. 40 let stride = 2 * num_threads; 41 let mut n = 3 + 2 * thread_id; 42 let batch_size = 500u64; 43 44 if thread_id == 0 { 45 // Count prime 2 once 46 primes_found.fetch_add(1, Ordering::Relaxed); 47 } 48 49 while running.load(Ordering::Relaxed) { 50 let mut local_primes = 0u64; 51 52 for _ in 0..batch_size { 53 if is_prime(n) { 54 local_primes += 1; 55 } 56 n += stride; 57 } 58 59 primes_found.fetch_add(local_primes, Ordering::Relaxed); 60 numbers_tested.fetch_add(batch_size, Ordering::Relaxed); 61 } 62}