[racket] math/matrix

From: Neil Toronto (neil.toronto at gmail.com)
Date: Sun May 11 15:48:33 EDT 2014

The garbage collection time is probably from cleaning up boxed flonums, 
and possibly intermediate vectors. If so, a separate implementation of 
Gaussian elimination for the FlArray type would cut the GC time to 
nearly zero.

Neil ⊥

On 05/11/2014 01:36 PM, Jens Axel Søgaard wrote:
> Or ... you could take a look at
>
> https://github.com/plt/racket/blob/master/pkgs/math-pkgs/math-lib/math/private/matrix/matrix-gauss-elim.rkt
>
> at see if something can be improved.
>
> /Jens Axel
>
>
> 2014-05-11 21:30 GMT+02:00 Jens Axel Søgaard <jensaxel at soegaard.net>:
>> Hi Eduardo,
>>
>> The math/matrix library uses the arrays from math/array to represent matrices.
>>
>> If you want to try the same representation as Bigloo, you could try Will Farr's
>> matrix library:
>>
>> http://planet.racket-lang.org/package-source/wmfarr/simple-matrix.plt/1/1/planet-docs/simple-matrix/index.html
>>
>> I am interested in hearing the results.
>>
>> /Jens Axel
>>
>>
>>
>> 2014-05-11 21:18 GMT+02:00 Eduardo Costa <edu500ac at gmail.com>:
>>> What is bothering me is the time Racket is spending in garbage collection.
>>>
>>> ~/wrk/scm/rkt/matrix$ racket matrix.rkt
>>> 0.9999999999967226
>>> cpu time: 61416 real time: 61214 gc time: 32164
>>>
>>> If I am reading the output correctly, Racket is spending 32 seconds out of
>>> 61 seconds in garbage collection.
>>>
>>>   I am following Junia Magellan's computer language comparison and I cannot
>>> understand why Racket needs the garbage collector for doing Gaussian
>>> elimination. In a slow Compaq/HP machine, solving a system of 800 linear
>>> equations takes 17.3 seconds in Bigloo, but requires 58 seconds in Racket,
>>> even after removing the building of the linear system from consideration.
>>> Common Lisp is also much faster than Racket in processing arrays. I would
>>> like to point out that Racket is very fast in general. The only occasion
>>> that it lags badly behind Common Lisp and Bigloo is when one needs to deal
>>> with arrays.
>>>
>>> Basically, Junia is using Rasch method to measure certain latent traits of
>>> computer languages, like productivity and coaching time. In any case, she
>>> needs to do a lot of matrix calculations to invert the Rasch model. Since
>>> Bigloo works with homogeneous vectors, she wrote a few macros to access the
>>> elements of a matrix:
>>>
>>> (define (mkv n) (make-f64vector n))
>>> (define $ f64vector-ref)
>>> (define $! f64vector-set!)
>>> (define len f64vector-length)
>>>
>>> (define-syntax $$
>>>     (syntax-rules ()
>>>        (($$ m i j) (f64vector-ref (vector-ref m i) j))))
>>>
>>> (define-syntax $$!
>>>     (syntax-rules ()
>>>        (($$! matrix row column value)
>>>         ($! (vector-ref matrix row) column value))))
>>>
>>> I wonder whether homogeneous vectors would speed up Racket. In the same
>>> computer that Racket takes 80 seconds to build and invert a system of
>>> equations, Bigloo takes 17.3 seconds, as I told before. Common Lisp is even
>>> faster. However, if one subtracts the gc time from Racket's total time, the
>>> result comes quite close to Common Lisp or Bigloo.
>>>
>>> ~/wrk/bgl$ bigloo -Obench bigmat.scm -o big
>>> ~/wrk/bgl$ time ./big
>>> 0.9999999999965746 1.000000000000774 0.9999999999993039 0.9999999999982576
>>> 1.000000000007648 0.999999999996588
>>>
>>> real    0m17.423s
>>> user    0m17.384s
>>> sys    0m0.032s
>>> ~/wrk/bgl$
>>>
>>> Well, bigloo may perform global optimizations, but Common Lisp doesn't. When
>>> one is not dealing with matrices, Racket is faster than Common Lisp. I hope
>>> you can tell me how to rewrite the program in order to avoid garbage
>>> collection.
>>>
>>> By the way, you may want to know why not use Bigloo or Common Lisp to invert
>>> the Rasch model. The problem is that Junia and her co-workers are using
>>> hosting services that do not give access to the server or to the jailshell.
>>> Since Bigloo requires gcc based compilation, Junia discarded it right away.
>>> Not long ago, the hosting service stopped responding to the sbcl Common Lisp
>>> compiler for reasons that I cannot fathom.  Although Racket 6.0 stopped
>>> working too, Racket 6.0.1 is working fine. This left Junia, her co-workers
>>> and students with Racket as their sole option. As for myself, I am just
>>> curious.
>>>
>>>
>>> 2014-05-11 6:23 GMT-03:00 Jens Axel Søgaard <jensaxel at soegaard.net>:
>>>
>>>> 2014-05-11 6:09 GMT+02:00 Eduardo Costa <edu500ac at gmail.com>:
>>>>> The documentation says that one should expect typed/racket to be faster
>>>>> than
>>>>> racket. I tested the math/matrix library and it seems to be almost as
>>>>> slow
>>>>> in typed/racket as in racket.
>>>>
>>>> What was (is?) slow was a call in an untyped module A to a function
>>>> exported
>>>> from a typed module B. The functions in B must check at runtime that
>>>> the values coming from A are of the correct type. If the A was written
>>>> in Typed Racket, the types would be known at compile time.
>>>>
>>>> Here math/matrix is written in Typed Racket, so if you are writing an
>>>> untyped module, you will in general want to minimize the use of,say,
>>>> maxtrix-ref. Instead operations that works on entire matrices or
>>>> row/columns are preferred.
>>>>
>>>>> (: sum : Integer Integer -> Flonum)
>>>>> (define (sum i n)
>>>>>    (let loop ((j 0) (acc 0.0))
>>>>>      (if (>= j mx) acc
>>>>>          (loop (+ j 1) (+ acc (matrix-ref A i j))) )))
>>>>>
>>>>> (: b : (Matrix Flonum))
>>>>> (define b (build-matrix mx 1 sum))
>>>>
>>>> The matrix b contains the sums of each row in the matrix.
>>>> Since matrices are a subset of arrays, you can use array-axis-sum,
>>>> which computes sum along a given axis (i.e. a row or a column when
>>>> speaking of matrices).
>>>>
>>>> (define A (matrix [[0. 1. 2.]
>>>>                     [3. 4. 5.]
>>>>                     [6. 7. 8.]]))
>>>>
>>>>> (array-axis-sum A 1)
>>>> - : (Array Flonum)
>>>> (array #[3.0 12.0 21.0])
>>>>
>>>> However as Eric points out, matrix-solve is an O(n^3) algorithm,
>>>> so the majority of the time is spent in matrix-solve.
>>>>
>>>> Apart from finding a way to exploit the relationship between your
>>>> matrix A and the column vector b, I see no obvious way of
>>>> speeding up the code.
>>>>
>>>> Note that when you benchmark with
>>>>
>>>>     time racket matrix.rkt
>>>>
>>>> you will include startup and compilation time.
>>>> Therefore if you want to time the matrix code,
>>>> insert a literal (time ...) call.
>>>>
>>>> --
>>>> Jens Axel Søgaard
>>>
>>>
>>
>>
>>
>> --
>> --
>> Jens Axel Søgaard
>
>
>


Posted on the users mailing list.