我正试图通过实施一个用于填料的砂轮来进行平行加工,操作顺序大致如下,
N
,构造8个不同的形式辐条
{p, p + 30, p+ 60, ..., p + 30n]
中的p {{1, 7, 11, 13, 17, 19, 23, 29}
。我的代码如下所示(primes
和primes2
分别是简单筛子和轮筛的单线程实现,用于比较)
我遇到的问题是,我目前尝试执行第4步(在函数primes4
,primes5
和primes6
中)都是主导步骤1-3。
任何人都可以给我任何指示我应该如何完成primes3
(仅执行步骤1-3)?否则,如果这是绝望的,有人可以解释一些其他策略,将单独的线程分开工作分开吗?
(defn spoke-30 [p N]
(map #(+ p (* %1 30)) (range 0 (/ N 30))))
(defn interleaved-spokes
"returns all the spoke30 elements less than or equal to N (but not the first which is 1)"
[N]
(rest (filter #(< % N) (apply interleave (map #(spoke-30 % N) '(1 7 11 13 17 19 23 29))))))
(defn get-orbit
"for a spacing diff, generates the orbit of diff under + in Z_{30}"
[diff]
(map #(mod (* diff %) 30) (range 0 30)))
(defn _all-orbits
"returns a map of maps where each key is an element of (1 7 11 13 17 19 23 29),
and each value is the orbit of that element under + in Z_30)"
[]
(let [primes '(1 7 11 13 17 19 23 29)]
(zipmap primes (map #(zipmap (get-orbit %) (range 30 0 -1)) primes))))
(def all-orbits (memoize _all-orbits))
(defn start
"for a prime N and a spoke on-spoke, determine the optimal starting point"
[N on-spoke]
(let [dist (mod (- N) 30)
lowest (* (((all-orbits) dist) on-spoke) N)
sqrN (* N N)]
; this might be one away from where I need to be, but it is a cheaper
; calculation than the absolute best start.
(cond (>= lowest sqrN) lowest
(= lowest N) (* 31 N)
true (+ lowest (* N 30 (int (/ N 30)))))))
(defn primes2 [bound]
(let [bset (new java.util.BitSet bound)
sqrtBound (Math/sqrt bound)
pList (interleaved-spokes sqrtBound)]
(.flip bset 2 bound)
(doseq [i (range 9 bound 6)] (.clear bset i)) ;clear out the special case 3s
(doseq [i (range 25 bound 10)] (.clear bset i)) ;clear out the special case 5s
(doseq [x '(1 7 11 13 17 19 23 29)
y pList
z (range (start y x) bound (* 30 y))]
(.clear bset z))
(conj (filter (fn [x] (.get bset x)) (range 1 bound 2)) 2)))
(defn scaled-start [N on-spoke]
(let [dist (mod (- N) 30)
k (((all-orbits) dist) on-spoke)
lowest (int (/ (* k N) 30))
remaining (* (int (/ (- N k) 30)) N)
start (+ lowest remaining)]
(if (> start 0) start N)))
;TODO do I even *need* this bitset!?? ...
(defn mark-composites [bound spoke pList]
(let [scaledbound (int (/ bound 30))
bset (new java.util.BitSet scaledbound)]
(if (= spoke 1) (.set bset 0)) ; this won't be marked as composite - but it isn't prime!
(doseq [x pList
y (range (scaled-start x spoke) scaledbound x)]
(.set bset y))
[spoke bset]))
;TODO now need to find a quick way of reconstructing the required list
; need the raw bitsets ... will then loop over [0 scaledbound] and the bitsets, adding to a list in correct order if the element is true and not present already (it shouldn't!)
(defn primes3 [bound]
(let [pList (interleaved-spokes (Math/sqrt bound))]
(pmap #(mark-composites bound % pList) '(1 7 11 13 17 19 23 29))))
(defn primes4 [bound]
(let [pList (interleaved-spokes (Math/sqrt bound))
bits (pmap #(mark-composites bound % pList) '(1 7 11 13 17 19 23 29))
L (new java.util.ArrayList)]
(.addAll L '(2 3 5))
(doseq [z (range 0 (int (/ bound 30))) [x y] bits ]
(if (not (.get y z)) (.add L (+ x (* 30 z))))
(println x y z L)
)))
(defn primes5 [bound]
(let [pList (interleaved-spokes (Math/sqrt bound))
bits (pmap #(mark-composites bound % pList) '(1 7 11 13 17 19 23 29))]
(for [z (range 0 (int (+ 1 (/ bound 30)))) [x y] bits ]
(if (not (.get y z)) (+ x (* 30 z))))
))
(defn primes6 [bound]
(let [pList (interleaved-spokes (Math/sqrt bound))]
(concat '(2 3 5) (filter #(not= % 0) (apply interleave (pmap #(mark-composites2 bound % pList) '(1 7 11 13 17 19 23 29)))))))
(defn primes [n]
"returns a list of prime numbers less than or equal to n"
(let [bs (new java.util.BitSet n)]
(.flip bs 2 n)
;(doseq [i (range 4 n 2)] (.clear bs i)) ;clear out the special case 2s
(doseq [i (range 3 (Math/sqrt n))]
(if (.get bs i) ; it seems faster to check if odd than to range in steps of 2
(doseq [j (range (* i i) n (* 2 i))] (.clear bs j))))
(conj (filter (fn [x] (.get bs x)) (range 1 n 2)) 2)))
一些时间是:
user=> (time (count (primes 1000000)))
"Elapsed time: 117.023543 msecs"
78498
user=> (time (count (primes2 1000000)))
"Elapsed time: 77.10944 msecs"
78498
user=> (time (count (primes3 1000000)))
"Elapsed time: 22.447898 msecs"
8
user=> (time (count (primes4 1000000)))
"Elapsed time: 647.586234 msecs"
78506
user=> (time (count (primes5 1000000)))
"Elapsed time: 721.62017 msecs"
266672
user=> (time (count (primes6 1000000)))
"Elapsed time: 306.280182 msecs"