Performance Clojure中向量和数组的性能

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

我正在努力解决这个问题。这是一个标准的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-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))))