end*_*gin 4 performance clojure
我想知道是否有人可以帮助我在Clojure 1.3中使用此代码片段的性能.我正在尝试实现一个简单的函数,它需要两个向量并完成一系列产品.
因此,假设向量是X(大小为10,000个元素)和B(大小为3个元素),并且乘积之和存储在向量Y中,数学上看起来像这样:
Y0 = B0*X2 + B1*X1 + B2*X0
Y1 = B0*X3 + B1*X2 + B2*X1
Y2 = B0*X4 + B1*X3 + B2*X2
等等 ...
对于此示例,Y的大小最终将为9997,对应于(10,000 - 3).我已经设置了接受任何大小的X和B的函数.
这是代码:它基本上(count b)从X一次获取元素,反转它,映射*到B并对结果序列的内容求和以产生Y的元素.
(defn filt [b-vec x-vec]
(loop [n 0 sig x-vec result []]
(if (= n (- (count x-vec) (count b-vec)))
result
(recur (inc n) (rest sig) (conj result (->> sig
(take (count b-vec))
(reverse)
(map * b-vec)
(apply +)))))))
Run Code Online (Sandbox Code Playgroud)
在让X (vec (range 1 10001))和B成为时[1 2 3],此功能大约需要6秒才能运行.我希望有人可以建议改进运行时间,无论是算法,还是我可能滥用的语言细节.
谢谢!
PS我已经完成(set! *warn-on-reflection* true)但没有得到任何反射警告信息.
你不必多次使用计数.下面的代码只计算一次计数
(defn filt [b-vec x-vec]
(let [bc (count b-vec) xc (count x-vec)]
(loop [n 0 sig x-vec result []]
(if (= n (- xc bc))
result
(recur (inc n) (rest sig) (conj result (->> sig
(take bc)
(reverse)
(map * b-vec)
(apply +))))))))
(time (def b (filt [1 2 3] (range 10000))))
=> "Elapsed time: 50.892536 msecs"
Run Code Online (Sandbox Code Playgroud)
如果你真的想要这种计算的最佳性能,你应该使用数组而不是矢量.阵列具有许多性能优势:
代码将是这样的:
(defn filt [^doubles b-arr
^doubles x-arr]
(let [bc (count b-arr)
xc (count x-arr)
rc (inc (- xc bc))
result ^doubles (double-array rc)]
(dotimes [i rc]
(dotimes [j bc]
(aset result i (+ (aget result i) (* (aget x-arr (+ i j)) (aget b-arr j))))))
result))
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
212 次 |
| 最近记录: |