Hello!
If you feel like taking on a little challenge read on!
I am currently working on a gambit UI kit that is containing glfw and OpenGL
(It will be open source and free)
It will also be native to gambit, so no weird hocus pokus required! Well a little bit of black magic and sacrificial of virgins is always needed to get things to run properly...
(The result will hopefully be better then my so called jokes)
Since modern OpenGL requires some hefty matrix math I need to make a matrix math library. Since I want this to be multi platform compatible and easy to use even in the interpreter. I have to do all this in scheme. (Except we're forced to allocate the the scheme binary vectors in c to make them not move during garbage collection)
But back to business! I've made the following macro and procedure to test matrix multiplication
(To test simply copy paste into interpreter)
But as you will se on the test i've added on the last row of code this is a pretty "slow" procedure.
The question is, How do you make this quicker?
Thank you for reading this long! :)
!!!! warning "ugly" code #######################CODE START############################
;; because the multiplication of matricies require a ton of commands we make a macro! :D
;; the macro requires the nr of columns and the number of rows and the current position of both column and row
(define-macro (f32-mat*-elem columns rows column-pos row-pos first-vector second-vector)
(let ((result '()))
(let loop ((i 0))
(set! result (cons `(##fl* (##f32vector-ref ,first-vector ,(fx+ row-pos i))
(##f32vector-ref ,second-vector ,(fx+ column-pos (* i columns)))
) result))
(if (not (eq? i rows)) (loop (+ i 1)))
)
(set! result (reverse result))
`(##fl+ ,@result)
))
;; multiplies two matricites of the dimetions 4x4 into one
(define (f32mat4* first-vector second-vector)
(f32vector ;;-still
(f32-mat*-elem 4 4 0 0 first-vector second-vector) (f32-mat*-elem 4 4 1 0 first-vector second-vector) (f32-mat*-elem 4 4 2 0 first-vector second-vector) (f32-mat*-elem 4 4 3 0 first-vector second-vector)
(f32-mat*-elem 4 4 0 1 first-vector second-vector) (f32-mat*-elem 4 4 1 1 first-vector second-vector) (f32-mat*-elem 4 4 2 1 first-vector second-vector) (f32-mat*-elem 4 4 3 1 first-vector second-vector)
(f32-mat*-elem 4 4 0 2 first-vector second-vector) (f32-mat*-elem 4 4 1 2 first-vector second-vector) (f32-mat*-elem 4 4 2 2 first-vector second-vector) (f32-mat*-elem 4 4 3 2 first-vector second-vector)
(f32-mat*-elem 4 4 0 3 first-vector second-vector) (f32-mat*-elem 4 4 1 3 first-vector second-vector) (f32-mat*-elem 4 4 2 3 first-vector second-vector) (f32-mat*-elem 4 4 3 3 first-vector second-vector)
))
(define x (f32vector 1. 2. 3. 4. 1. 2. 3. 4. 1. 2. 3. 4. 1. 2. 3. 4.))
(define y (f32vector 1. 2. 3. 4. 1. 2. 3. 4. 1. 2. 3. 4. 1. 2. 3. 4.))
(time (let loop ((i 1000)) (f32mat4* x y) (if (not (eq? i 0)) (loop (- i 1 ))))) ####################### CODE END ####################################
Afficher les réponses par date
On May 21, 2014, at 9:15 AM, Tomas Möre tomas.o.more@gmail.com wrote:
Since modern OpenGL requires some hefty matrix math I need to make a matrix math library. Since I want this to be multi platform compatible and easy to use even in the interpreter. I have to do all this in scheme. (Except we're forced to allocate the the scheme binary vectors in c to make them not move during garbage collection)
But back to business! I've made the following macro and procedure to test matrix multiplication
(To test simply copy paste into interpreter)
But as you will se on the test i've added on the last row of code this is a pretty "slow" procedure.
The question is, How do you make this quicker?
Model it on tfo-combine in bench/src/nucleic.scm after untarring misc/bench.tgz in the gambit source directory.
Brad
(Resent because of mail screwup.)
On May 21, 2014, at 9:15 AM, Tomas Möre tomas.o.more@gmail.com wrote:
Since modern OpenGL requires some hefty matrix math I need to make a matrix math library. Since I want this to be multi platform compatible and easy to use even in the interpreter. I have to do all this in scheme. (Except we're forced to allocate the the scheme binary vectors in c to make them not move during garbage collection)
But back to business! I've made the following macro and procedure to test matrix multiplication
(To test simply copy paste into interpreter)
But as you will se on the test i've added on the last row of code this is a pretty "slow" procedure.
The question is, How do you make this quicker?
Model it on tfo-combine in bench/src/nucleic.scm after untarring misc/bench.tgz in the gambit source directory.
Brad
On 21-05-14 15:15, Tomas Möre wrote:
Hello!
Since modern OpenGL requires some hefty matrix math I need to make a matrix math library.
Hi Tomas,
first make it correct, then you can make it fast, then you can use macros to unroll loops (assuming the compiler doesn't already do it automatically).
Below are two functions that multiply matrices, the first in the style you used, the second maybe more direct. They appear to be equally fast (slow?).
Maybe you also want to take a look at existing code, for example http://aleph0.info/scheme/matrix-bench-gambit.scm or http://docs.racket-lang.org/math/matrices.html or http://wiki.call-cc.org/eggref/4/blas or maybe a CL one. That will also allow you to compare performance and see how you're doing.
Marijn
(define (mat*~ m w dim) (define (mat*-elem i j) (let loop ((d 0) (res 0)) (cond ((< d dim) (loop (+ d 1) (+ res (* (vector-ref m (+ (* i dim) d)) (vector-ref w (+ (* d dim) j)))))) (#t res)))) (let ((res (make-vector (* dim dim) 0))) (let loop ((r 0)) (cond ((< r dim) (let lp ((c 0)) (cond ((< c dim) (vector-set! res (+ (* r dim) c) (mat*-elem r c)) (lp (+ c 1))))) (loop (+ r 1))))) res))
(define (mat* m w dim) (let ((res (make-vector (* dim dim) 0))) (let loop ((r 0)) (cond ((< r dim) (let lop ((c 0)) (cond ((< c dim) (let lp ((i 0)) (cond ((< i dim) (vector-set! res (+ (* r dim) c) (+ (vector-ref res (+ (* r dim) c)) (* (vector-ref m (+ (* r dim) i)) (vector-ref w (+ (* i dim) c))))) (lp (+ i 1))))) (lop (+ c 1))))) (loop (+ r 1))))) res))
(define m (vector 1 0 1 0 1 3 7 0 1))
(define w (vector 1 0 0 0 1 0 0 0 1))
(pp (mat*~ m w 3)) (pp (mat* m w 3))
(pp (mat*~ w m 3)) (pp (mat* w m 3))
(time (let loop ((i 10000)) (mat*~ m w 3) (if (> i 0) (loop (- i 1)))))
(time (let loop ((i 10000)) (mat* m w 3) (if (> i 0) (loop (- i 1)))))