Clojure:在几个期货中运行计算并不能加快我的计划

时间:2015-05-02 20:19:52

标签: multithreading clojure future

我刚刚开始在Clojure中编写以下代码,用于通过蒙特卡罗模拟估算pi。我基本上想要创建X线程,每个线程计算落在单位圆中的随机点数并返回它。然后我的主线程将它们全部加起来并计算Pi。

但是,在同一个线程中运行所有样本比通过future在多个线程之间拆分计算更快。为什么呢?

(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)

基于调试结果的其他几个注释:

  • 正在创建正确的期货数量

  • 每个未来都在计算正确的模拟数量

  • 这是在多个线程和处理器核心上运行

1 个答案:

答案 0 :(得分:0)

如果您将第二次运行中的期货数量减少到2(和8),会发生什么?管理线程和期货的时间可能大于分割工作所节省的时间。

产生比硬件可支持的更多线程通常会产生相反的效果(因为线程必须共享内核并且需要付出代价)。如果你只用两个线程来获得速度增益(与1相比),那么其他地方可能出现了问题。