Live data from Hacker News

Programming language ray tracing benchmarks project

github.com

81–90 of 90 posts

Re: Programming language ray tracing benchmarks project

#81
You should see a performance boost in the Haskell implementation by compiling with GHC's LLVM backend[0]. Another Haskell ray tracer ran 30 % faster than the native codegen this way[1].

[0]https://gitlab.haskell.org/ghc/ghc/wikis/commentary/compiler...

[1]http://blog.llvm.org/2010/05/glasgow-haskell-compiler-and-ll...

Re: Programming language ray tracing benchmarks project

#82
post #23

Earlier quoted context omitted.

I wouldn’t give much weight to those benchmark numbers at this point. Some of those language versions are quite out of date...

The numbers are indeed out of date. I re-ran the tests for some of the C and Nim programs using Nim 0.19.4 and gcc 7.3.0 on Windows 10. Here are the results: crb-omp 0m22.949s crb 0m23.240s crb_opt 0m31.404s nimrb_pmap 0m8.828s nimrb_fn 0m22.988s nimrb 0m26.556s The base C code is faster than base Nim code. The optimised C code is significantly slower than everything else(!?). The Nim program that uses a threadpool i…

If you are using a current version of your C compiler and can consistently reproduce those numbers just by adding something like -O3, you should probably file a bug report. Optimizers can go wrong and sometimes pessimize things a bit, but an almost 50% slowdown from enabling optimizations would be treated as an important bug to fix. (Though people are saying that significant amounts of time in the benchmark are spent in random number generation and output, so maybe try to find out first if the problem lies in one of those.)

Re: Programming language ray tracing benchmarks project

#83
post #27

The most impressive result here is Lua -- not far behind C! LuaJIT is amazing. Good to see a few languages like Nim and Rust actually beating C for raw performance, too.

Sarcasm?

Unfortunately for me, Hanlon’s Razor applies.

Re: Programming language ray tracing benchmarks project

#84

Earlier quoted context omitted.

The numbers are indeed out of date. I re-ran the tests for some of the C and Nim programs using Nim 0.19.4 and gcc 7.3.0 on Windows 10. Here are the results: crb-omp 0m22.949s crb 0m23.240s crb_opt 0m31.404s nimrb_pmap 0m8.828s nimrb_fn 0m22.988s nimrb 0m26.556s The base C code is faster than base Nim code. The optimised C code is significantly slower than everything else(!?). The Nim program that uses a threadpool i…

If you are using a current version of your C compiler and can consistently reproduce those numbers just by adding something like -O3, you should probably file a bug report. Optimizers can go wrong and sometimes pessimize things a bit, but an almost 50% slowdown from enabling optimizations would be treated as an important bug to fix. (Though people are saying that significant amounts of time in the benchmark are spent…

Ah, nevermind, (a) even the "non-optimized" C version uses -O3, and (b) the "C" and the "optimized C" programs differ not only in compiler flags but they are actually different source codes. Specifically, the "optimized C" version doesn't use the faster random number generator.

If you fix that, on my machine it's 17.3 seconds for the base C version and 13.4 for the optimized one, i.e., a 22% improvement from turning on the extra optimizations (-march=native and -ffast-math).

And for whatever it's worth, because some people love hating on GCC in favor of Clang, my Clang timings are 19.5 and 16.5 seconds, respectively.

Re: Programming language ray tracing benchmarks project

#85

Ordered by realtime, fastest to slowest for those like me who got annoyed by the scrolling up and down trying to compare: Rust (1.13.0-nightly) 1m32.392s Nim (0.14.2) 1m53.320s C 1m59.116s Julia (0.4.6) 2m01.166s Crystal (0.18.7) 2m01.735s C Double Precision 2m26.546s Java (1.7.0_111) 2m36.949s Nim Double Precision (0.14.2) 3m19.547s OCaml 3m59.597s Go 1.6 6m44.151s node.js (6.2.1) 7m59.041s node.js (5.7.1) 8m49.170s…

Python gets 20% faster if you use `__slots__` on the Vector class which is created and destroyed millions of times. It's still the second-slowest, but it's a nice improvement :P

Re: Programming language ray tracing benchmarks project

#86
post #73

Ordered by realtime, fastest to slowest for those like me who got annoyed by the scrolling up and down trying to compare: Rust (1.13.0-nightly) 1m32.392s Nim (0.14.2) 1m53.320s C 1m59.116s Julia (0.4.6) 2m01.166s Crystal (0.18.7) 2m01.735s C Double Precision 2m26.546s Java (1.7.0_111) 2m36.949s Nim Double Precision (0.14.2) 3m19.547s OCaml 3m59.597s Go 1.6 6m44.151s node.js (6.2.1) 7m59.041s node.js (5.7.1) 8m49.170s…

I rewrote the Go benchmark to be a mechanical translation of C and it performs much better. C (gcc -O3): 23.8s Julia (julia 1.1.0): 32.8s Go (alt) (go 1.12): 39.3s Java (java 1.8.0_60): 44.2s Go (org) (go 1.12): 64.8s OCaml (ocaml 4.07.1): 79.1s JS (node 11.14.0): 137.0s Pypy (pypy 6.0.0): 139.4s C# (mono 4.2.1): 187.3s Rust: DOES NOT COMPILE So Go is only twice as slow as C, not thrice as slow. This puts it just ahe…

Note that the Java impl is creating objects all over the place in the inner loop - madness!

I'm sure a "mechanical translation of [the] C" version would improve things for the Java ver as well. If we removed startup costs (the class file validation, etc) I'd expect it to be on par with C.

Re: Programming language ray tracing benchmarks project

#87
post #73

Earlier quoted context omitted.

I rewrote the Go benchmark to be a mechanical translation of C and it performs much better. C (gcc -O3): 23.8s Julia (julia 1.1.0): 32.8s Go (alt) (go 1.12): 39.3s Java (java 1.8.0_60): 44.2s Go (org) (go 1.12): 64.8s OCaml (ocaml 4.07.1): 79.1s JS (node 11.14.0): 137.0s Pypy (pypy 6.0.0): 139.4s C# (mono 4.2.1): 187.3s Rust: DOES NOT COMPILE So Go is only twice as slow as C, not thrice as slow. This puts it just ahe…

Note that the Java impl is creating objects all over the place in the inner loop - madness! I'm sure a "mechanical translation of [the] C" version would improve things for the Java ver as well. If we removed startup costs (the class file validation, etc) I'd expect it to be on par with C.

The startup costs are fixed (they don't increase linearly with the number of loop iterations) and for such a small program, they could not reasonbly explain more than 1s of the 20s gap between C and Java. Also, I don't think it's "allocating objects in an inner loop", because Java's allocations are super cheap (bump allocations) if the escape analyzer doesn't keep them on the stack in the first place.

That said, after examining this benchmark further, I don't think it's very good since the sequences returned by the random number generators are not controlled for (each implementation uses its own standard library RNG with their own seeds, so the sequences will vary from language to language). This likely causes more loop iterations, but considering the loop termination condition, the theoretical distribution of RNG outputs, and the trivial work done in the loop body, I doubt that the delta in loop iterations can explain any significant portion of the gap. Rather, I think the gap is simply a difference in performance of the RNGs themselves--C and Rust use a poor man's RNG (xorshift) which performs very well for this exercise but is not a good general purpose RNG (and standard library RNGs are optimized for the general case). When I rewrote the Go version, using the xorshift implementation made the most significant impact (15s), although I'm not 100% sure that the output of the RNG isn't just causing it to run the RNG less frequently. I opened up this ticket against the project: https://github.com/niofis/raybench/issues/15.

Re: Programming language ray tracing benchmarks project

#88
post #53

Earlier quoted context omitted.

shouldn't rust being faster than C be something of a red flag that they aren't quite the same algorithm? Or that the algorithm is sub-optimal?

It got me thinking as well, so I ventured and did some experiments on this, and found that the main difference is the algorithm used for the RNG; C's std lib uses a slower one (which also is thread safe, and butchered OpenMP performance). You can take a look at a more apples to apples comparison in the latest update for crb.c which uses a xor128 rng; rust is still a little faster (especially when going multithreaded)…

[deleted]

Re: Programming language ray tracing benchmarks project

#89
post #53

Earlier quoted context omitted.

shouldn't rust being faster than C be something of a red flag that they aren't quite the same algorithm? Or that the algorithm is sub-optimal?

It got me thinking as well, so I ventured and did some experiments on this, and found that the main difference is the algorithm used for the RNG; C's std lib uses a slower one (which also is thread safe, and butchered OpenMP performance). You can take a look at a more apples to apples comparison in the latest update for crb.c which uses a xor128 rng; rust is still a little faster (especially when going multithreaded)…

fwiw, I looked at some of the quicker c/rust examples, without too much other analysis

  crb-vec-omp //I added some #pragma omp to crb-vec
  executable size:
    18k
  time:
    real 0m3.630s
  valgrind: 
    ==17703== HEAP SUMMARY:
    ==17703==     in use at exit: 7,408 bytes in 15 blocks
    ==17703==   total heap usage: 20 allocs, 5 frees, 
  14,790,856 bytes allocated

  rsrb_alt_mt.rs
  executable size:
      426k
  time: 
    real 0m1.630s
  valgrind: 
    ==7221== HEAP SUMMARY:
    ==7221==     in use at exit: 43,120 bytes in 216 blocks
    ==7221==   total heap usage: 256 allocs, 40 frees, 
  11,113,784 bytes allocated
and because we have a number of tiny single cpu vm's out there (which would also benefit from a performant language) I gave it a shot there:

  :~# time ./rsrb_alt_mt
  ./rsrb_alt_mt: /lib64/libc.so.6: version `GLIBC_2.18' not 
  found (required by ./rsrb_alt_mt)

  real 0m0.002s
  user 0m0.002s
  sys 0m0.000s

  :~# time ./crb-vec-omp 

  real 0m24.234s
  user 0m24.160s
  sys 0m0.035s
so rust appears broken on centos 7.5 (no, I'm not going to edit the binary). But that is an insta-deal breaker for us.

Re: Programming language ray tracing benchmarks project

#90
post #76
post #53

Earlier quoted context omitted.

It got me thinking as well, so I ventured and did some experiments on this, and found that the main difference is the algorithm used for the RNG; C's std lib uses a slower one (which also is thread safe, and butchered OpenMP performance). You can take a look at a more apples to apples comparison in the latest update for crb.c which uses a xor128 rng; rust is still a little faster (especially when going multithreaded)…

Have you tried passing everything by value? That is, instead of: bool hit_sphere(const struct sphere* sp, const struct ray* ray, struct hit* hit) you write: static bool hit_sphere(struct sphere sp, struct ray ray, struct hit hit) IME, clang is insanely good at optimizing pass by value calls.

fwiw, I took a stab at replacing a bunch of => with . and ran it: time ./crb-vec-omp real 0m0.764s

which is more than twice as fast as the rust example,

but it didn't create the right output...

if you get bored would you mind taking a stab at adding parallel and modifying crb-vec.c https://github.com/niofis/raybench , I definitely think you might be on to something here.

Post reply on HN