Fast vector math in Clojure / Incanter

后端 未结 5 412
感情败类
感情败类 2021-01-30 09:40

I\'m currently looking into Clojure and Incanter as an alternative to R. (Not that I dislike R, but it just interesting to try out new languages.) I like Incanter and find the s

5条回答
  •  抹茶落季
    2021-01-30 10:01

    My final solutions

    After all the testing I found two slightly different ways to do the calculation with sufficient speed.

    First I've used the function diff with different types of return values, below is the code returning a vector, but I have also timed a version returning a double-array (replace (vec y) with y) and Incanter.matrix (replace (vec y) with matrix y). This function is only based on java arrays. This is based on Jouni's code with some extra type hints removed.

    Another approach is to do the calculations with Java arrays and store the values in a transient vector. As you see from the timings this is slightly faster than approach 1 if you wan't the function to return and array. This is implemented in function difft.

    So the choice really depends on what you wan't to do with the data. I guess a good option would be to overload the function so that it returns the same type that was used in the call. Actually passing a java array to diff instead of a vector makes ~1s faster.

    Timings for the different functions:

    diff returning vector:

    (time (def y (diff x)))
    "Elapsed time: 4733.259 msecs"
    

    diff returning Incanter.matrix:

    (time (def y (diff x)))
    "Elapsed time: 2599.728 msecs"
    

    diff returning double-array:

    (time (def y (diff x)))
    "Elapsed time: 1638.548 msecs"
    

    difft:

    (time (def y (difft x)))
    "Elapsed time: 3683.237 msecs"
    

    The functions

    (use 'incanter.stats)
    (def x (vec (sample-normal 1e7)))
    
    (defn diff [x]
      (let [y (double-array (dec (count x)))
            x (double-array x)] 
       (dotimes [i (dec (count x))]
         (aset y i
           (- (aget x (inc i))
                       (aget x i))))
       (vec y)))
    
    
    (defn difft [x]
      (let [y (vector (range n))
            y (transient y)
            x (double-array x)]
       (dotimes [i (dec (count x))]
         (assoc! y i
           (- (aget x (inc i))
                       (aget x i))))
       (persistent! y))) 
    

提交回复
热议问题