q
...@purdue.edu wrote:
> I wrote Stalin.
> Please send me the exact code that you ran. I believe that I can make
> it considerably faster. It appears that you modified the code that I
> posted to take command line arguments. If one is not careful, this
> could slow things down considerably.
Sure. Here's the code and some new (longer) timings:
Here are the compile lines I used on x86:
ocamlopt -inline 100 -ffast-math ray.ml -o ray
g++ -O3 -march=athlon-tbird -ffast-math ray.cpp -o ray
mlton ray.sml
javac ray.java
stalin -d0 -d1 -d5 -d6 -On -q -d -architecture IA32-align-double
-no-clone-size-limit -split-even-if-no-widening -copt -O2 -copt
-fomit-frame-pointer -copt -malign-double qobi
Running times for level=9, n=512 and ss=4 on 900MHz Athlon T-bird:
46.181s OCaml
33.086s C++ (gcc)
35.298s SML (MLton)
147.242s Java (Sun JDK 1.5)
73.976s Scheme (Stalin)
Compile times:
0.349s OCaml
5.205s C++ (gcc)
17.093s SML (MLton)
7.361s Java (Sun JDK 1.5)
94.647s Scheme (Stalin)
Here are the compile lines I used on AMD64:
ocamlopt -inline 100 ray.ml -o ray
g++ -O3 ray.cpp -o ray
mlton ray.sml
javac ray.java
stalin -d0 -d1 -d5 -d6 -On -q -d -architecture IA32-align-double
-no-clone-size-limit -split-even-if-no-widening -copt -O2 -copt
-fomit-frame-pointer -copt -malign-double qobi
(load (compile-file "nathan.lisp"))
Running times for level=9, n=512 and ss=4 on 1.8GHz Athlon64:
12.154s OCaml
12.226s C++ (gcc)
12.407s SML (MLton)
21.616s Java (Sun JDK 1.5)
26.867s Scheme (Stalin)
56.366s Lisp (SBCL)
MLton, Stalin and SBCL are run from 32-bit mode. All others from 64-bit
mode.
Compile times:
1.378s OCaml
2.279s C++ (gcc)
7.786s SML (MLton)
2.650s Java (Sun JDK 1.5)
94.647s Scheme (Stalin)
0.445s Lisp (SBCL)
Here's the Stalin implementation "qobi.sc" that I used:
(define-structure point x y z)
(define-structure obj c r objs)
(define-structure hit lam normal)
(define fail #f)
(define (fold-right f i l)
(if (null? l) i (f (car l) (fold-right f i (cdr l)))))
(define infinity (/ 1.0 0.0))
(define epsilon 1e-15)
(define (s*v s b)
(make-point (* s (point-x b)) (* s (point-y b)) (* s (point-z b))))
(define (v+v a b)
(make-point (+ (point-x a) (point-x b))
(+ (point-y a) (point-y b))
(+ (point-z a) (point-z b))))
(define (v-v a b)
(make-point (- (point-x a) (point-x b))
(- (point-y a) (point-y b))
(- (point-z a) (point-z b))))
(define (cpsv-v a b receiver)
(receiver (- (point-x a) (point-x b))
(- (point-y a) (point-y b))
(- (point-z a) (point-z b))))
(define (dot a b)
(+ (* (point-x a) (point-x b))
(* (point-y a) (point-y b))
(* (point-z a) (point-z b))))
(define (dot1 ax ay az b)
(+ (* ax (point-x b)) (* ay (point-y b)) (* az (point-z b))))
(define (dot2 ax ay az bx by bz) (+ (* ax bx) (* ay by) (* az bz)))
(define (unitise r) (s*v (/ 1.0 (sqrt (dot r r))) r))
(define (ray-sphere orig dir center radius)
(cpsv-v
center
orig
(lambda (vx vy vz)
(let* ((b (dot1 vx vy vz dir))
(disc (+ (- (* b b) (dot2 vx vy vz vx vy vz)) (* radius radius))))
(if (< disc 0.0)
infinity
(let ((t2 (+ b (sqrt disc))))
(if (< t2 0.0)
infinity
(let ((t1 (- b (sqrt disc))))
(if (> t1 0.0) t1 t2)))))))))
(define zero (make-point 0.0 0.0 0.0))
(define (intersect orig dir obj)
(let lp ((obj obj) (hit (make-hit infinity zero)))
(let ((l (ray-sphere orig dir (obj-c obj) (obj-r obj))))
(cond ((>= l (hit-lam hit)) hit)
((pair? (obj-objs obj)) (fold-right lp hit (obj-objs obj)))
((null? (obj-objs obj))
(make-hit l (unitise (v+v orig (v-v (s*v l dir) (obj-c obj))))))
(else (display "Bad obj") (display obj) (newline))))))
(define neg_light (unitise (make-point 1.0 3.0 -2.0)))
(define orig (make-point 0.0 0.0 -4.0))
(define (ray-trace dir scene)
(let* ((hit (intersect orig dir scene))
(lam (hit-lam hit))
(normal (hit-normal hit)))
(cond ((>= lam infinity) 0.0)
((< (hit-lam
(intersect
(v+v orig (v+v (s*v lam dir) (s*v (sqrt epsilon) normal)))
neg_light
scene))
infinity)
0.0)
(else (max 0.0 (dot normal neg_light))))))
(define (create level c r)
(let ((obj (make-obj c r '()))
(a (* 3.0 (/ r (sqrt 12.0)))))
(if (= level 1)
obj
(let ((aux (lambda (x z)
(create (- level 1) (v+v c (make-point x a z)) (* 0.5
r)))))
(make-obj c
(* 3.0 r)
(list obj
(aux (- a) (- a))
(aux a (- a))
(aux (- a) a)
(aux a a)))))))
(define level 6)
(define level (or (and (= (length argv) 3)
(string->number (vector-ref argv 1))) 9))
(define n 160)
(define n (or (and (= (length argv) 3)
(string->number (vector-ref argv 2))) 512))
(define ss 4)
(define scene (create level (make-point 0.0 -1.0 0.0) 1.0))
(define ss2 (* ss ss))
(define (aux x d) (+ (- x (/ n 2.0)) (/ d ss)))
(define (g x y)
(do ((dx 0 (+ dx 1))
(sum 0 (do ((dy 0 (+ dy 1))
(sum sum (+ sum
(ray-trace (unitise
(make-point (aux x dx)
(aux (- (- n 1) y) dy)
(exact->inexact n)))
scene))))
((>= dy ss) sum))))
((>= dx ss) sum)))
(define (pixel x y)
(write-char
(integer->char (inexact->exact (truncate (+ 0.5 (* 255 (/ (g x y)
ss2))))))))
(define n2 n)
(define (go)
(with-output-to-file "scheme.pgm"
(lambda ()
(display "P5")
(newline)
(display n)
(display " ")
(display n)
(newline)
(display 255)
(newline)
(do ((y 0 (+ y 1))) ((>= y n2))
(do ((x 0 (+ x 1))) ((>= x n))
(pixel x y))))))
(go)
--
Dr Jon D Harrop, Flying Frog Consultancy
http://www.ffconsultancy.com