Performance Clojure中向量和数组的性能
我正在努力解决这个问题。这是一个标准的DP问题,我写了一个O(n)解决方案:Performance Clojure中向量和数组的性能,performance,clojure,Performance,Clojure,我正在努力解决这个问题。这是一个标准的DP问题,我写了一个O(n)解决方案: (defn dp [v] (let [n (count v)] (loop [i 1 f (v 0) best f] (if (< i n) (let [fi (max (v i) (+ f (v i)))] (recur (inc i) fi (max fi best))) best)))) (defn positive-on
(defn dp
[v]
(let [n (count v)]
(loop [i 1 f (v 0) best f]
(if (< i n)
(let [fi (max (v i) (+ f (v i)))]
(recur (inc i) fi (max fi best)))
best))))
(defn positive-only
[v]
(reduce + (filterv #(> % 0) v)))
(defn line->ints
[line]
(->>
(clojure.string/split line #" ")
(map #(Integer. %))
(into [])
))
(let [T (Integer. (read-line))]
(loop [test 0]
(when (< test T)
(let [_ (read-line)
x (read-line)
v (line->ints x)
a (dp-array v)
b (let [p (positive-only v)]
(if (= p 0) (reduce max v) p))]
(printf "%d %d\n" a b))
(recur (inc test)))))
此阵列版本甚至更慢。在相同的输入上,它花费33秒,比矢量版本慢得多。我认为这种缓慢是由于装箱和拆箱造成的。我试图添加类型提示,但遇到了运行时错误。有人能帮我改进一下dp阵列的功能吗?谢谢
另外,如果有人知道如何改进矢量版本,我们将不胜感激
更新:
最后,我成功地接受了clojure程序,不是通过优化动态编程函数,而是通过将(Integer.str)
更改为(Integer/parseInt-str)
。这样,在从字符串转换为整数时就避免了反射
我还用
int-array
将替换为array
。但是两种版本的速度仍然是相称的。我希望数组版本比向量版本快。Clojure编译器无法在参数v0具有未知类型的dp array
函数的数组版本中推断v
的类型。这会导致在评估以下alength
和aget
时产生反射成本。为了避免这些不必要的反射,您必须将替换为数组
,使用长数组
一个更好的仅用于正数的定义:#(apply+(filter pos?%)
如果您显式地为v创建int数组
,您可能会从dp数组
中看到更好的性能,否则,您将得到可以专门用于int的装箱和泛型数学。我怀疑您的问题是反射,而不是装箱/取消装箱。@Alex如果没有提示数组,您将看到反射和装箱/取消装箱,并且反射的修复也修复了装箱问题。
(defn dp-array
[v0]
(let [v (into-array v0)
n (int (alength v))]
(loop [i 1
f (aget v 0)
best f]
(if (< i n)
(let [fi (max (aget v i) (+ f (aget v i)))]
(recur (inc i) fi (max fi best)))
best))))