Skip to content

niofis/raybench

Repository files navigation

raybench

A simple implementation of a path tracer in different programming languages with some restrictions.

Checkout my blog posts about the development of this project.

## Restrictions Code should be simple, as in, easy to read and understand.

A single file per implementation, whenever possible.

Intersection finding algorithms must be the same in all implementations.

Brute force algorithm, no acceleration structures.

If the language allows vectorization, parallel or distributed processing, those must be used in different implementations, i.e. crb (C single threaded), cmprb (C using OpenMP, not yet implemented).

Code must follow best practices in formating and structure, according to the language in use.

Technical details

  • Output resolution: 1280x720
  • Max Depth: 5
  • Samples: 50
  • Only spheres
  • Image format: PPM

Other Info

The C language implementation will be used as baseline, crb.c.

This implementation takes around 2 minutes to render the scene on a Basic A1 Microsoft Azure VM instance. That means 1 Core, 1.75 GB RAM, Ubuntu Server 14.04 LTS.

processor       : 0
vendor_id       : GenuineIntel
cpu family      : 6
model           : 63
model name      : Intel(R) Xeon(R) CPU E5-2673 v3 @ 2.40GHz
stepping        : 2
microcode       : 0xffffffff
cpu MHz         : 2394.403
cache size      : 30720 KB
physical id     : 0
siblings        : 1
core id         : 0
cpu cores       : 1
apicid          : 0
initial apicid  : 0
fpu             : yes
fpu_exception   : yes
cpuid level     : 13
wp              : yes
flags           : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ss syscall nx lm constant_tsc rep_good nopl eagerfpu pni pclmulqdq ssse3 fma cx16 sse4_1 sse4_2 movbe popcnt aes xsave avx f16c rdrand hypervisor lahf_lm abm fsgsbase bmi1 avx2 smep bmi2 erms xsaveopt
bugs            :
bogomips        : 4788.80
clflush size    : 64
cache_alignment : 64
address sizes   : 42 bits physical, 48 bits virtual
power management:

Implementations

C (crb.c) (gcc (Ubuntu 7.4.0-1ubuntu1~18.04) 7.4.0)

$ gcc crb.c -o crb -std=c11 -O3 -lm -D_XOPEN_SOURCE=600
$ time ./crb

real    1m32.039s
user    1m30.197s
sys     0m1.039s

C with vector extensions (crb-vec.c)

$ gcc crb-vec.c -o crb-vec -std=c11 -O3 -lm -D_XOPEN_SOURCE=600
$ time ./crb-vec

real    1m15.193s
user    1m13.722s
sys     0m0.893s

C Double Precision (crb-dbl.c)

$ gcc crb-dbl.c -o crb-dbl -std=c11 -O3 -lm -D_XOPEN_SOURCE=600
$ time ./crb-dbl 

real	2m26.546s
user	2m25.856s
sys	  0m0.104s

Lua (luarb.lua)

$ time lua luarb.lua 

real    611m38.925s
user    605m54.136s
sys     0m37.716s
$time luajit luarb.lua 

real    225m58.621s
user    224m2.140s
sys     0m14.044s

Javascript (node.js v12.1.0)

$ time node jsrb.js

real    7m7.700s
user    6m50.256s
sys     0m13.321s

C# (.net core 2.2.203), improvements thanks to benaadams, FICTURE7 and lostmsu

dotnet build --configuration Release
$ time dotnet run --configuration Release

real    2m34.957s
user    2m30.212s
sys     0m2.625s

Haskell (The Glorious Glasgow Haskell Compilation System, version 8.6.3), improvements thanks to jmikkola

$ ghc -O3 -o hsrb hsrb.hs
$ time ./hsrb

real    35m35.170s
user    34m39.833s
sys     0m30.666s

Python (version 2.7.15rc1)

$ time python pyrb.py

real    327m45.162s
user    320m5.804s
sys     3m44.487s
$ time pypy pyrb.py

real    14m2.406s
user    13m55.292s
sys     0m1.416s

Lisp (lisprb.lisp)

$ time sbcl --script lisprb.lisp 

real    24m43.216s
user    24m27.772s
sys     0m4.972s

OCaml (ocamlrb.ml)

$ ocamlopt -inline 9 -unsafe -ccopt -O9 -o ocamlrb ocamlrb.ml
$ time ./ocamlrb 

real	3m59.597s
user	3m58.036s
sys	  0m0.432s

Elixir

$ time elixir elixirrb.exs

real    123m59.025s
user    118m2.504s
sys     4m16.504s

Elixir MP

$ time elixir elixirrb.mp.exs

real    138m48.241s
user    132m20.264s
sys     4m54.372s

Go (version 1.12.5), thanks to weberc2

$ time ./gorb                                                                                                                                                                   
                                                                                                                                                                                                          
real    4m7.536s                                                                                                                                                                                          
user    3m57.942s                                                                                                                                                                                         
sys     0m6.745s

Nim (Compiler Version 0.19.4 [Linux: amd64])

$ time ./nimrb

real	1m29.043s
user	1m27.010s
sys	0m1.139s

Nim Double Precision (Compiler Version 0.19.4 [Linux: amd64])

$ time ./nimrb_dbl 

real	2m17.034s
user	2m13.979s
sys	0m1.779s

Crystal (version 0.18.7)

$ crystal build --release crrb.cr
$ time ./crrb 

real	2m1.735s
user	2m1.116s
sys	0m0.140s

Rust (rustc 1.34.1 (fc50f328b 2019-04-24)), thanks to tilpner

$ time cargo script rsrb.rs -d rand=0.3.14
Progress: 99%
real    1m12.964s
user    1m10.887s
sys     0m1.410s

Rust Alt (rustc 1.34.1 (fc50f328b 2019-04-24))

$ time cargo script rsrb_alt.rs -d rand=0.3.14

real    1m15.509s
user    1m13.896s
sys     0m0.962s

Java (1.7.0_111, OpenJDK IcedTea 2.6.7)

$ time java javarb 

real	2m36.949s
user	2m34.344s
sys	  0m1.832s

Julia (version 1.1.0), thanks to pierroelmito and staticfloat

$ time julia jlrb.jl
120.827142 seconds (663.19 k allocations: 44.870 MiB, 0.01% gc time)

real    2m2.025s
user    1m59.348s
sys     0m1.345s

Ruby (2.7.0dev (2019-05-13 trunk 2dc613815d) [x86_64-linux]), thanks to briankung

$ time ruby rbrb.rb

real    207m12.067s
user    202m19.372s
sys     2m16.687s

Ubuntu 20.04.3 LTS (AMD EPYC 7452 32-Core Processor)

Language Running Time (s) Version
Rust Alt 17.4755 rustc 1.53.0
Swift 21.4647 Swift version 5.4.2 (swift-5.4.2-RELEASE)
Nim 23.2373 Nim Compiler Version 1.4.8 [Linux: amd64]
Scala 24.8810 Scala compiler version 2.13.6 -- Copyright 2002-2021, LAMP/EPFL and Lightbend, Inc.
Webassembly 28.9251 wasmer 2.0.0
C# 31.4052 5.0.202
C 34.6629 gcc (GCC) 10.3.0
Java 35.0083 javac 16
Lisp 38.4177 SBCL 2.1.2.nixos
Go 43.0722 go version go1.16.7 linux/amd64
Javascript 108.9169 v16.8.0
LuaJIT 2209.7823 LuaJIT 2.1.0-beta3 -- Copyright (C) 2005-2021 Mike Pall. https://luajit.org/
Wren 3080.1662 wren 0.3.0
Haxe 3858.7298 4.2.1
Lua 7450.4894 Lua 5.2.4 Copyright (C) 1994-2015 Lua.org, PUC-Rio

Ubuntu 20.04.3 LTS (AMD EPYC 7281 16-Core Processor)

Language Running Time (s) Version
Wren 0.0075
Rust Alt 22.1112 rustc 1.53.0
Swift 27.4875 Swift version 5.4.2 (swift-5.4.2-RELEASE)
Nim 29.8019 Nim Compiler Version 1.4.8 [Linux: amd64]
Scala 40.7265 Scala compiler version 2.13.6 -- Copyright 2002-2021, LAMP/EPFL and Lightbend, Inc.
C# 45.8363 5.0.202
C 49.5445 gcc (GCC) 10.3.0
Lisp 50.5706 SBCL 2.1.2.nixos
Java 51.8577 javac 16
Go 58.5328 go version go1.16.7 linux/amd64
Webassembly 63.6267 wasmer 2.0.0
Javascript 182.6355 v16.8.0
LuaJIT 3255.1736 LuaJIT 2.1.0-beta3 -- Copyright (C) 2005-2021 Mike Pall. https://luajit.org/
Haxe 6044.8931 4.2.1
Lua 10408.4416 Lua 5.2.4 Copyright (C) 1994-2015 Lua.org, PUC-Rio