我刚开始学习Clojure,写了以下代码来通过蒙特卡洛模拟估算pi。我想创建X个线程,每个线程计算落在单位圆内的随机点数,并返回它。然后我的主线程对它们加总并计算π。
然而,使用同一个线程运行所有样本比通过futures将计算分配给几个线程更快。为什么呢?
(defn sumFutures [workerFutures acc i]
(if (= -1 i)
acc
(recur workerFutures (+ acc @(nth workerFutures i)) (dec i))))
(defn getResults [workerFutures numSamples]
(* 4.0 (/ (sumFutures workerFutures 0 (dec (count workerFutures))) numSamples)))
(defn isInCircle []
(let [x (rand) y (rand)]
(if (<= (+ (* x x) (* y y)) 1)
1
0)))
(defn countInCircle [remaining acc]
(if (zero? remaining)
acc
(recur (dec remaining) (+ acc (isInCircle)))))
(defn getWorker [samplesPerWorker]
(future
(countInCircle samplesPerWorker 0)))
(defn addWorker [workers samplesPerWorker]
(conj workers (getWorker samplesPerWorker)))
(defn getWorkers [workers samplesPerWorker remWorkers]
(if (not (zero? remWorkers))
(recur (addWorker workers samplesPerWorker) samplesPerWorker (dec remWorkers))
(doall workers)))
(defn main [numSamples numWorkers]
(getResults (getWorkers [] (quot numSamples numWorkers) numWorkers) numSamples))
;; Run all in 1 thread
(main 1000000 1)
;; Split among 100 futures (at least 8 threads)
;; SLOWER
(main 1000000 100)
根据调试结果,以下是一些注意事项:
创建了正确数量的 futures
每个 future 正确计算了模拟次数
该过程在多个线程和处理器核心上运行
numSamples
- 你不应该按照numWorkers
的数量进行分割吗? - Piotrek Bzdyl