我想知道是否有人可以帮助我解决 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 +)))))))
设 X 为
(vec (range 1 10001))
和 B 是 [1 2 3]
,此函数大约需要 6 秒才能运行。我希望有人可以提出改进运行时间的建议,无论是算法方面的,还是我可能会滥用的语言细节。谢谢!
附言我已经做了
(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"
关于Clojure 1.3 中的函数性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9661535/