【发布时间】:2014-11-11 13:52:14
【问题描述】:
clojure.org/refs 有一点修改的例子
(defn mod-nth [v i f] (assoc v i (f (v i))))
(defn run [oper nvecs nitems nthreads niters]
(let [vec-refs (vec (map (comp ref vec)
(partition nitems (repeat (* nvecs nitems) 0))))
sum #(reduce + %)
swap #(let [v1 (rand-int nvecs)
v2 (rand-int nvecs)
i1 (rand-int nitems)
i2 (rand-int nitems)]
(dosync
(let [temp (nth @(vec-refs v1) i1)]
(oper (vec-refs v1) mod-nth i1 inc)
(oper (vec-refs v2) mod-nth i2 dec))))
report #(do
(prn (map deref vec-refs))
(println "Sum:"
(reduce + (map (comp sum deref) vec-refs))))]
(report)
(dorun (apply pcalls (repeat nthreads #(dotimes [_ niters] (swap)))))
(report)))
(time (run alter 100 10 10 100000))
样本输出为
([0 0 0 0 0 0 0 0 0 0] [...])
Sum: 0
([15 -14 -8 57 -26 -12 -49 -29 33 -3] [...])
Sum: 0
"Elapsed time: 1995.938147 msecs"
我不是交换唯一数字,而是将一个向量元素从一个向量元素转移到另一个。
这个操作可以被假定为可交换的,所以还有另一个测试——除了使用commute而不是alter之外,它是相同的
(time (run commute 100 10 10 100000))
带有样例输出
([0 0 0 0 0 0 0 0 0 0] [...])
Sum: 0
([8 48 -10 -41 -17 -32 -4 50 -31 88] [...])
Sum: 0
"Elapsed time: 3141.591517 msecs"
令人惊讶的是,第一个示例大约在 2 seconds 中运行,而第二个示例需要 3 seconds
但正如提到的in this SO answer
commute是 alter 的优化版本,适用于那些事情顺序真的无关紧要的时代
在这种简单的情况下,它需要更多时间来完成相同的工作,如何对其进行优化?
commute的目的是什么?
【问题讨论】: