在 clojure 中初始化大向量的有效方法
efficient way to initialize a large vector-of in clojure
clojure 中的 Vector-of 是一种执行操作的高效方式,因为内部值是未装箱的。我可以这样创建一个数组:
(time (count (apply vector-of :double (repeat 100000 0))));
; "Elapsed time: 1703.597 msecs"
但是速度很慢。有没有更快的方法(必须有)?注意:向量的预分配对于 assoc 很重要,因为如果 assoc 尝试设置超出向量长度的元素,则会产生越界错误。
编辑:
目前有一个解决方案(参见答案)。 Leon Grapenthin 在 github here.
上将此作为错误发布
运行 OP 的代码,用于在我的机器上获取基准时间。 (Mac Pro 2009 2.66 GHz 四核 Intel Xeon,48 GB RAM。Clojure 1.6.0。Java 1.8。0_40 Java HotSpot(TM) 64 位服务器VM.)
user> (time (count (apply vector-of :double (repeat 100000 0))))
"Elapsed time: 992.688709 msecs"
100000
尝试(repeat 100000 0.0)
消除长整数到双整数的转换。变化不大。
user> (time (count (apply vector-of :double (repeat 100000 0.0))))
"Elapsed time: 965.876047 msecs"
100000
创建向量,然后添加元素,速度更快:
user> (time (count (into (vector-of :double) (repeat 100000 0.0))))
"Elapsed time: 52.856371 msecs"
100000
有点快,不要构建惰性序列:
(defn n-conj [n coll elem]
(if (zero? n)
coll
(recur (dec n) (conj coll elem) elem)))
(time (count (n-conj 100000 (vector-of :double) 0.0)))
"Elapsed time: 37.86183 msecs"
100000
clojure 中的 Vector-of 是一种执行操作的高效方式,因为内部值是未装箱的。我可以这样创建一个数组:
(time (count (apply vector-of :double (repeat 100000 0))));
; "Elapsed time: 1703.597 msecs"
但是速度很慢。有没有更快的方法(必须有)?注意:向量的预分配对于 assoc 很重要,因为如果 assoc 尝试设置超出向量长度的元素,则会产生越界错误。
编辑:
目前有一个解决方案(参见答案)。 Leon Grapenthin 在 github here.
上将此作为错误发布运行 OP 的代码,用于在我的机器上获取基准时间。 (Mac Pro 2009 2.66 GHz 四核 Intel Xeon,48 GB RAM。Clojure 1.6.0。Java 1.8。0_40 Java HotSpot(TM) 64 位服务器VM.)
user> (time (count (apply vector-of :double (repeat 100000 0))))
"Elapsed time: 992.688709 msecs"
100000
尝试(repeat 100000 0.0)
消除长整数到双整数的转换。变化不大。
user> (time (count (apply vector-of :double (repeat 100000 0.0))))
"Elapsed time: 965.876047 msecs"
100000
创建向量,然后添加元素,速度更快:
user> (time (count (into (vector-of :double) (repeat 100000 0.0))))
"Elapsed time: 52.856371 msecs"
100000
有点快,不要构建惰性序列:
(defn n-conj [n coll elem]
(if (zero? n)
coll
(recur (dec n) (conj coll elem) elem)))
(time (count (n-conj 100000 (vector-of :double) 0.0)))
"Elapsed time: 37.86183 msecs"
100000