【发布时间】:2014-08-16 16:32:24
【问题描述】:
我正在尝试使用筛算法总结欧拉项目问题的素数。我正在使用一个可变集合来存储不是素数的数字,并使用“dosync”和“commute”来更新该集合(否则,如果它是不可变的,我会用完内存)。在 120 万个素数之前性能大致呈线性关系,但在 150 万个时性能很糟糕(7 秒对 64 秒)。任何想法我做错了什么?我的猜测是数字可能变得太大,或者更新可变集效率低下。
(defn mark-multiples [not-prime-set multiple prime-max]
(loop [ counter (long 2)
product (* counter multiple)]
(if (> product prime-max) not-prime-set
(do
(dosync (commute not-prime-set conj product))
(recur (inc counter) (* (inc counter) multiple))))))
(defn sieve-summation [prime-max]
(def not-prime-set (ref #{ (long 1) }) )
(loop [counter (long 2)
summation (long 0)]
(if (> counter prime-max) summation
(if (not (contains? @not-prime-set counter))
(do
(mark-multiples not-prime-set counter prime-max)
(recur (inc counter) (+ summation counter)))
(recur (inc counter) summation)))))
=>(时间(筛子总和 100000)) “经过时间:496.673 毫秒” 454396537
=>(时间(筛子总和 150000)) “经过时间:763.333 毫秒” 986017447
=>(时间(筛子总和 1000000)) “经过时间:6037.926 毫秒” 37550402023
=> (时间 (筛子总和 1100000)) “经过时间:6904.385 毫秒” 45125753695
=> (时间 (筛子总和 1200000)) “经过时间:7321.299 毫秒” 53433406131
=> (时间 (筛子总和 1500000)) “经过时间:64995.216 毫秒” 82074443256
----编辑----
感谢 A. Webb,很好的建议!你的代码有点慢,所以为了让它加速,我必须在一开始就制作非素数集瞬态,现在它运行得更快(大约 8 倍)。我仍然遇到内存不足的错误,所以我将尝试弄清楚如何增加 jvm 上的堆大小以查看是否可以解决它。我在 Mac 上的 Eclipse 上运行 Clojure,而且我是 Clojure 和 Mac 的新手。
我很想看看您如何进一步重构程序(保持基本相同的逻辑)以在 Clojure 中更加优雅。再次感谢。
(defn mark-multiples2 [not-prime-set prime prime-max]
(loop [multiple (* 2 prime) nps not-prime-set ]
(if (> multiple prime-max)
nps
(recur (+ multiple prime) (conj! nps multiple)))))
(defn sieve-summation2 [prime-max]
(loop [counter 2, summation 0, not-prime-set (transient #{1})]
(if (> counter prime-max)
summation
(if (not-prime-set counter)
(recur (inc counter) summation not-prime-set)
(recur (inc counter)
(+ summation counter)
(mark-multiples2 not-prime-set counter prime-max))))))
=> (时间 (sieve-summation2 100000)) “经过时间:124.781 毫秒” 454396537
=>(时间(筛子总和 100000)) “经过时间:876.744 毫秒” 454396537
【问题讨论】:
-
你的 jvm 的堆大小是多少?我没有看到 -Xmx1G 的退化
-
您应该使用 Clojure 1.6 - 哈希已经过大修,对于这个特定的用例可能会更好。
-
谢谢,我试试看。对于在 Mac 上运行 Clojure,你们都推荐什么?我感谢任何支持我的声誉的投票:)
-
Leiningen (lein) 是除了您选择的编辑器之外您所需要的一切。直接从站点安装,因为包管理器提供过时的版本。
标签: performance clojure