[racket] performance problem in math/matrix

From: Ray Racine (ray.racine at gmail.com)
Date: Sun Jan 20 16:40:15 EST 2013

Recall that last.  Always measure at the command line <sigh>.  I'm seeing
FlVector at 30% faster.

#lang typed/racket

(provide main)

(require racket/unsafe/ops
 racket/fixnum
         racket/flonum)

(define-type NF Nonnegative-Fixnum)

(: matrix* :
   FlVector FlVector Index Index Index
   -> FlVector)
(define (matrix* A B m p n)
  (define size (* m n))
  (define: v : FlVector (make-flvector size 0.0))
  (define index 0)
  (: loop-i : NF -> FlVector)
  (define (loop-i i)
    (cond [(< i m)
           (loop-j i 0)
           (loop-i (+ i 1))]
          [else v]))
  (: loop-j : NF NF -> Void)
  (define (loop-j i j)
    (when (< j n)
      (loop-k i j 0 0.0)
      (set! index (+ index 1))
      (loop-j i (+ j 1))))
  (: loop-k : NF NF NF Flonum -> Void)
  (define (loop-k i j k sum)
    (define i*p (* i p))
    (define k*n (* k n))
    (cond
     [(< k p)
      (loop-k i j (+ k 1)
      (+ sum
   (* (unsafe-flvector-ref A (+ i*p k))
(unsafe-flvector-ref B (+ k*n j)))))]
     [else
      (unsafe-flvector-set! v index sum)]))
  (loop-i 0))

(: mkFlVector (Fixnum (-> Flonum) -> FlVector))
(define (mkFlVector sz init)
  (let ((v (make-flvector sz)))
    (do ((i #{0 : Fixnum} (+ i 1)))
((>= i sz) v)
      (unsafe-flvector-set! v i (init)))))

(define: dim : Index 300)
(define: A : FlVector (mkFlVector (fx* dim dim) random))
(define: B : FlVector (mkFlVector (fx* dim dim) random))

(define (main)
  (collect-garbage)
  (collect-garbage)
  (let ((m (time (matrix* A B dim dim dim))))
    (void)))



On Sun, Jan 20, 2013 at 4:25 PM, Ray Racine <ray.racine at gmail.com> wrote:

> Modification of the above to use FlVector did not show a difference.
>
>
> On Sun, Jan 20, 2013 at 2:35 PM, Jens Axel Søgaard <jensaxel at soegaard.net>wrote:
>
>> 2013/1/20 Berthold Bäuml <berthold.baeuml at dlr.de>:
>> >> Ah! The Numpy example uses floats and not doubles.
>> >
>> > On my machine Numpy says it is using float64, hence, double.
>> >  big1.dtype.name -> float64
>>
>> Sorry for the confusion. I am used to the Racket documentation
>> were float means single precision, so I misinterpreted the Numpy
>> documentation.
>>
>> Also
>>
>> > numpy.random.random((5,5))
>> array([[ 0.04748764,  0.15242073,  0.2366255 ,  0.86926654,  0.16586114],
>>        [ 0.33117124,  0.7504899 ,  0.43179013,  0.1992083 ,  0.83266119],
>>        [ 0.25741902,  0.36912007,  0.38273193,  0.29622522,  0.75817261],
>>        [ 0.49313726,  0.20514653,  0.45329344,  0.964105  ,  0.77459153],
>>        [ 0.5267172 ,  0.87269101,  0.34530438,  0.38218051,  0.05107181]])
>>
>> suggested, that the numbers were single precision. It turns out
>> that random only produces 53 bit random floats.
>>
>> Anyways, here is a standard matrix multiplication algorithm in
>> Typed Racket.
>>
>> #lang typed/racket
>> (require racket/unsafe/ops
>>          racket/flonum)
>>
>> (define-type NF Nonnegative-Fixnum)
>>
>> (: matrix* :
>>    (Vectorof Flonum) (Vectorof Flonum) Index Index Index
>>    -> (Vectorof Flonum))
>> (define (matrix* A B m p n)
>>   (define size (* m n))
>>   (define: v : (Vectorof Flonum) (make-vector size 0.0))
>>   (define index 0)
>>   (: loop-i : NF -> (Vectorof Flonum))
>>   (define (loop-i i)
>>     (cond [(< i m)
>>            (loop-j i 0)
>>            (loop-i (+ i 1))]
>>           [else v]))
>>   (: loop-j : NF NF -> Void)
>>   (define (loop-j i j)
>>     (when (< j n)
>>       (loop-k i j 0 0.0)
>>       (set! index (+ index 1))
>>       (loop-j i (+ j 1))))
>>   (: loop-k : NF NF NF Flonum -> Void)
>>   (define (loop-k i j k sum)
>>     (define i*p (* i p))
>>     (define k*n (* k n))
>>     (cond
>>       [(< k p)
>>        (loop-k i j (+ k 1)
>>                (+ sum
>>                   (* (unsafe-vector-ref A (+ i*p k))
>>                      (unsafe-vector-ref B (+ k*n j)))))]
>>       [else
>>        (vector-set! v index sum)]))
>>   (loop-i 0))
>>
>> (define dim 200)
>> (define A (build-vector (* dim dim) (λ (_) (random))))
>> (define B (build-vector (* dim dim) (λ (_) (random))))
>> (collect-garbage)
>> (collect-garbage)
>> (define A*B (time (matrix* A B dim dim dim)))
>>
>> /Jens Axel
>>
>> ____________________
>>   Racket Users list:
>>   http://lists.racket-lang.org/users
>>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.racket-lang.org/users/archive/attachments/20130120/517a83d1/attachment-0001.html>

Posted on the users mailing list.