Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Performance of function in Clojure 1.3

I was wondering if someone could help me with the performance of this code snippet in Clojure 1.3. I am trying to implement a simple function that takes two vectors and does a sum of products.

So let's say the vectors are X (size 10,000 elements) and B (size 3 elements), and the sum of products are stored in a vector Y, mathematically it looks like this:

Y0 = B0*X2 + B1*X1 + B2*X0

Y1 = B0*X3 + B1*X2 + B2*X1

Y2 = B0*X4 + B1*X3 + B2*X2

and so on ...

For this example, the size of Y will end up being 9997, which corresponds to (10,000 - 3). I've set up the function to accept any size of X and B.

Here's the code: It basically takes (count b) elements at a time from X, reverses it, maps * onto B and sums the contents of the resulting sequence to produce an element of 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 +)))))))

Upon letting X be (vec (range 1 10001)) and B being [1 2 3], this function takes approximately 6 seconds to run. I was hoping someone could suggest improvements to the run time, whether it be algorithmic, or perhaps a language detail I might be abusing.

Thanks!

P.S. I have done (set! *warn-on-reflection* true) but don't get any reflection warning messages.

like image 552
endbegin Avatar asked Dec 05 '22 17:12

endbegin


1 Answers

You are using count many times unnecessary. Below code calculate count one time only

(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"
like image 154
Ankur Avatar answered Jan 12 '23 12:01

Ankur