Google Mail Calendar Documents Reader Web more »
Recently Visited Groups | Help | Sign in
Google Groups Home
Port my ray tracer
There are currently too many topics in this group that display first. To make this topic appear first, remove this option from another topic.
There was an error processing your request. Please try again.
flag
  Messages 26 - 30 of 30 - Collapse all  -  Translate all to Translated (View all originals) < Older 
The group you are posting to is a Usenet group. Messages posted to this group will make your email address visible to anyone on the Internet.
Your reply message has not been sent.
Your post was successful
 
From:
To:
Cc:
Follow-up To:
Add Cc | Add Follow-up to | Edit Subject
Subject:
Validation:
For verification purposes please type the characters you see in the picture below or the numbers you hear by clicking the accessibility icon. Listen and type the numbers that you hear
 
Jon Harrop  
View profile   Translate to Translated (View Original)
 More options 4 June 2005, 00:29
Newsgroups: comp.lang.functional
From: Jon Harrop <use...@jdh30.plus.com>
Date: Sat, 04 Jun 2005 00:29:36 +0100
Local: Sat 4 June 2005 00:29
Subject: Re: Port my ray tracer

Mark Carroll wrote:
> Maybe see how large the programme is after gzip or some other
> compression? That'll help discount for repetitious scaffolding.

That sounds like a measure of the information content, which should be the
same for all languages. We want to measure the exact opposite - the amount
of unnecessary code that has to be written.

--
Dr Jon D Harrop, Flying Frog Consultancy
http://www.ffconsultancy.com


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message, you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Matthias Blume  
View profile   Translate to Translated (View Original)
 More options 5 June 2005, 04:51
Newsgroups: comp.lang.functional
From: Matthias Blume <f...@my.address.elsewhere>
Date: Sat, 04 Jun 2005 22:51:18 -0500
Local: Sun 5 June 2005 04:51
Subject: Re: Port my ray tracer

Jon Harrop <use...@jdh30.plus.com> writes:
>> Where is the code actually used for benchmarking, BTW?

> Here's the OCaml:

[... big snip ... ]

Ok, I took the trouble and translated your Ocaml code to SML for use
under SML/NJ.  (MLton needs a minor adjustment.)  The code is only a
few lines longer than the original and should come in under 100loc
when ignoring comments and blank lines.

On an old 400 MHz Celeron, the program runs almost 30% faster than the
original SML code that you posted earlier.  I'd be interested to hear
how it fares on the Athlon...

Matthias

------------------

(* This is a straight translation of Jon Harrop's OCaml ray tracer code
 * for the "Great Computer Language Shootout", with very minor modifications.
 * Transliteration for SML/NJ done by Matthias Blume. *)

(* The following comment was in the original Ocaml code.  It does not
 * refer to differences between the Ocaml and SML/NJ versions: *)

(* This implementation differs from the original in several ways:

   Uses an implicit scene, generated as a ray is traced rather than being
   precalculated and stored explicitly in a tree.

   Specialized shadow-ray intersection functions. *)

structure Ray:sig val main:string*string list->OS.Process.status end = struct

val delta = Math.sqrt 2.22044604925031e~16

(* 3D vector and associated functions *)
type vec = real * real * real
infix 7  *| fun s *| (x, y, z) = (s*x, s*y, s*z) : vec    
infix 6 |+| fun (x, y, z) |+| (x', y', z') = (x+x', y+y', z+z') : vec
infix 6 |-| fun (x, y, z) |-| (x', y', z') = (x-x', y-y', z-z') : vec
infix 7 |*| fun (x, y, z) |*| (x', y', z') = x*x'+y*y'+z*z' : real
fun unitise r = (1.0 / Math.sqrt (r |*| r)) *| r
fun ~|(x,y,z) = (~x,~y,~z) : vec

(* Calculate the parametric intersection of the given ray with the given
sphere. *)
fun ray_sphere (orig, dir, center, radius) =
    let val v = center |-| orig
        val b = v |*| dir
        val disc = b * b - v |*| v + radius * radius
    in if disc < 0.0 then Real.posInf
       else let val disc = Math.sqrt disc
                val t2 = b + disc
            in if t2 < 0.0 then Real.posInf
               else let val t1 = b - disc in if t1 > 0.0 then t1 else t2 end
            end
    end

(* Calculate whether or not the given ray intersects the given sphere. *)
fun ray_sphere' (orig, dir, center, radius) =
    let val v = center |-| orig
        val b = v |*| dir
        val disc = b * b - v |*| v + radius * radius
    in if disc < 0.0 then false else b + Math.sqrt disc >= 0.0 end

(* Ratio of the radii of one level of spheres to the next. *)
val s = 6.0 / Math.sqrt 12.0

(* Find the first intersection point of the given ray with the scene. *)
fun intersect (level, orig, dir) =
    let fun of_scene (center, radius, lambda, normal, level) =
            if level = 1 then
                let val lambda' = ray_sphere (orig, dir, center, radius)
                in if lambda' >= lambda then (lambda, normal)
                   else (lambda', unitise (orig |+| lambda' *| dir |-| center))
                end
            else if ray_sphere (orig, dir, center, 3.0 * radius) >= lambda
            then (lambda, normal)
            else let val accu = of_scene (center, radius, lambda, normal, 1)
                     val r = 0.5 * radius val l = level - 1 val r' = s * r
                     fun h (dx, dz, (lam, norm)) =
                         of_scene (center |+| (dx, r', dz), r, lam, norm, l)
                     val mr' = ~r'
                 in h (r', mr', h (r', r', h (mr', r', h (mr', mr', accu))))
                 end
    in of_scene ((0.0, ~1.0, 0.0), 1.0, Real.posInf, (0.0, 0.0, 0.0), level) end

(* Find if the given ray intersects the scene. *)
fun intersect' (level, orig, dir) =
    let fun of_scene (center, radius, level) =
            if level = 1 then ray_sphere' (orig, dir, center, radius) else
      (* Exploit short-circuit evaluation of boolean comparisons to
       * terminate this function early. *)
              ray_sphere' (orig, dir, center, (3.0 * radius)) andalso
              (of_scene (center, radius, 1) orelse
               let val r = 0.5 * radius val l = level-1 val r' = s * r
               in of_scene (center |+| (~r', r', ~r'), r, l) orelse
                  of_scene (center |+| (r', r', ~r'), r, l) orelse
                  of_scene (center |+| (~r', r', r'), r, l) orelse
                  of_scene (center |+| (~r', r', r'), r, l)
               end)
    in of_scene ((0.0, ~1.0, 0.0), 1.0, level) end

(* Trace a single ray by casting it into the scene and, if it intersects
   anything, casting a second ray toward the light to determine occlusion.
*)
fun ray_trace (l, light, orig, dir) =
    let val (lam, n) = intersect (l, orig, dir)
    in if lam >= Real.posInf then 0.0
       else let val g = ~ (n |*| light)
    (* If we are on the shadowed side of a sphere then don't bother casting
a
       shadow ray as we know it will intersect the same sphere. *)
            in if g<=0.0 orelse intersect' (l, orig|+|lam*|dir|+|delta*|n, ~|light)
               then 0.0 else g
            end
    end

(* Ray trace the scene at the given resolution. *)
fun doit n (* Resolution *) =
    let val n2 = n div 2 val rn = real n val ns = Int.toString n
        val light = unitise (~1.0, ~3.0, 2.0) (* Light direction *)
        val level = 6 val ss = 4 (* ss: oversampling *)
        val rss' = 1.0 / real ss val rss'sq255 = rss' * rss' * 255.0
        fun yl y = if y < 0 then OS.Process.success else xl (0, y)
        and xl (x, y) = if x >= n then yl (y-1) else dxl (0.0, 0, x, y)
        and dxl (g, dx, x, y) =
            if dx < ss then dyl (g, 0, dx, x, y)
            else (print (String.str (chr (Real.trunc (0.5 + g * rss'sq255))));
                  xl (x+1, y))
        and dyl (g, dy, dx, x, y) =
            if dy >= ss then dxl (g, dx+1, x, y)
            else let val orig = (0.0, 0.0, ~4.0)
                     fun cvt (w, dw) = real (w-n2) + real dw * rss'
                     val dir = unitise (cvt (x, dx), cvt (y, dy), rn)
                 in dyl (g+ray_trace (level, light, orig, dir), dy+1, dx, x, y)
                 end
    in print (concat ["P5\n", ns, " ", ns, "\n255\n"]); yl (n-1) end

fun main (_, arg :: _) = doit (getOpt (Int.fromString arg, 256))
  | main _ = doit 256
end


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message, you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Dr Jon D Harrop  
View profile   Translate to Translated (View Original)
 More options 5 June 2005, 18:05
Newsgroups: comp.lang.functional
From: "Dr Jon D Harrop" <j...@ffconsultancy.com>
Date: 5 Jun 2005 10:05:48 -0700
Local: Sun 5 June 2005 18:05
Subject: Re: Port my ray tracer

Matthias Blume wrote:
> Ok, I took the trouble and translated your Ocaml code to SML for use
> under SML/NJ.  (MLton needs a minor adjustment.)  The code is only a
> few lines longer than the original and should come in under 100loc
> when ignoring comments and blank lines.

That's great, thank you. :-)

> On an old 400 MHz Celeron, the program runs almost 30% faster than the
> original SML code that you posted earlier.  I'd be interested to hear
> how it fares on the Athlon...

Using AMD64 OCaml but x86 Mlton and SML/NJ (are there AMD64 versions?)
I get:

Compiler LOC Time
Mlton     80 2.950
Mlton     88 2.571
Mlton     91 3.569
SML/NJ    80 7.487
SML/NJ    88 6.738
SML/NJ    91 3.738
ocamlopt  61 4.078
ocamlopt  67 3.845
ocamlopt  78 3.184

The tree versions are:

1. Minimal
2. Specialised "intersect" function for shadow rays
3. Implicit scene

Interestingly, the "implicit scene" Mlton implementation is much
slower. Both Mlton and SML/NJ will probably do a lot better if I can
get native AMD64 code gens working.

Cheers,
Jon.


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message, you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Matthew Fluet  
View profile   Translate to Translated (View Original)
 More options 5 June 2005, 19:20
Newsgroups: comp.lang.functional
From: Matthew Fluet <mfl...@acm.org>
Date: Sun, 05 Jun 2005 14:20:55 -0400
Local: Sun 5 June 2005 19:20
Subject: Re: Port my ray tracer

> Using AMD64 OCaml but x86 Mlton and SML/NJ (are there AMD64 versions?)

MLton does not have a native AMD64 port at the current time.
I do not believe that SML/NJ has a native AMD64 port either.

    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message, you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Jon Harrop  
View profile   Translate to Translated (View Original)
 More options 7 June 2005, 10:16
Newsgroups: comp.lang.functional
From: Jon Harrop <use...@jdh30.plus.com>
Date: Tue, 07 Jun 2005 10:16:52 +0100
Local: Tues 7 June 2005 10:16
Subject: Re: Port my ray tracer

Matthew Fluet wrote:
>> Using AMD64 OCaml but x86 Mlton and SML/NJ (are there AMD64 versions?)

> MLton does not have a native AMD64 port at the current time.
> I do not believe that SML/NJ has a native AMD64 port either.

That's a great shame. ocamlopt is relatively much faster on AMD64 than on
x86. I suspect SML/NJ and Mlton could be similarly much faster on AMD64.

Here are some results for comparison between 32- and 64-bit processors:

ss=4 level=9 n=512 Athlon T-bird

Compiler LOC Run Time
smlnj     79 83.470
smlnj     84 57.112
smlnj     90 47.253
smlnj     94 45.499
ocamlopt  60 81.846
ocamlopt  65 52.961
ocamlopt  72 52.578
ocamlopt  76 47.331
g++      106 62.597
g++      121 42.399
g++      130 36.419
g++      135 35.268
mlton     79 30.679
mlton     84 23.539
mlton     90 21.647
mlton     94 18.966

ss=4 level=9 n=512 Athlon 64

Compiler LOC Run Time
smlnj     79 39.092
smlnj     84 26.444
smlnj     90 22.246
smlnj     94 21.530
ocamlopt  60 26.474
ocamlopt  65 17.950
ocamlopt  72 16.657
ocamlopt  76 16.270
g++      106 24.395
g++      121 16.441
g++      130 14.841
g++      135 14.733
mlton     79 14.827
mlton     84 10.546
mlton     90  8.682
mlton     94  8.390

I'm curious as to why x86 ocamlopt shows no improvement moving from version
2 to version 3 (specialised shadow rays), whereas all other languages on
both platforms show significant improvement.

--
Dr Jon D Harrop, Flying Frog Consultancy
http://www.ffconsultancy.com


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message, you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
End of messages < Older 
« Back to Discussions « Newer topic     Older topic »

Create a group - Google Groups - Google Home - Terms of Service - Privacy Policy
©2009 Google