My brain still hurts from thinking about parallelizing prime number generation. I think the key is still to find primes two at a time in parallel, meaning that it’s only useful if you want a list, which is necessary to find the nth prime anyway.

So, I am starting with a rewrite of prime number generation — this one is simpler for me to understand and for some reason runs three times faster.

(defn divisible? [x y]

(= (rem x y) 0)

)

(defn is-prime? [p known-primes]

(every? (fn [kp] (not (divisible? p kp))) known-primes)

)

(defn primes-in-list [potential-primes known-primes]

(let [p (first potential-primes)]

(if (is-prime? p known-primes)

(lazy-cons

p

(primes-in-list (rest potential-primes) (conj known-primes p)))

(primes-in-list (rest potential-primes) known-primes)

)

)

)

(def primes (primes-in-list (iterate inc 2) []))

(time (reduce + (take 1000 primes)))

(time (reduce + (take 1000 primes)))

It’s also lazy. Not sure why it’s so much faster. Now that I can provide a list of potentials, I’ll be able to run two lists in parallel, and then I have to reduce them in the main thread. When I get the lists back, I need to make sure that they aren’t divisible by each other (since they won’t be in each others list of known primes).