7 ms·
Doubling Mono’s Float Speed
- bjourne 9y agoIt pains me to hear about developers doing the wrong thing just to beat a dumb benchmark. If you really care about cpu raytracing performance, you need to write handcrafted simd code and C# default float handling is of no consequence to you. Correctness > speed.
- benaadams 9y agoAnd you want more correct then you should be using double or decimal - you shouldn't really be expecting that all the calculations for a float are done in double then converted back to float. Decimal in .NET is 128bit, range (-7.9 x 10^28 to 7.9 x 10^28) / (10^0 to 10^28), 28-29 significant digits
- mikeash 9y agoDoing 32-bit math on 32-bit floats doesn’t seem like the wrong thing to me. It’s exactly what I’d expect when I use that data type.
- brighteyes 9y agoMaybe GP misspoke with "wrong", but a valid point was raised there, maybe not in the clearest way: If you are trying to write a super-fast raytracer or game or some such, you will get the best results by writing SIMD manually. Otherwise, you are benchmarking how well autovectorization works in the various compilers and JITs you are testing. Now, specifically here it looks like Mono had a bunch of other problems they had to fix to get to the right ballpark (not using the right data type, etc.), which is what the blogpost focuses on. And it's nice to see speedups for C# code there. Still, though, if you need maximal perf, raw SIMD is necessary. Comparing to a C++ version with SIMD might have been interesting, for example. (Likely the reason Burst is "faster than C++" is that it happens to autovectorize that code better.)
- vanderZwan 9y agoYou raise a valid point, but given that GP ended their argument with "correctness > speed" I do not believe that it was the point they were going for.
- SimonPStevens 9y agoThis isn't really to do with raytracer perf. It's about how Miguel de Icaza (The creator of Mono) improved Mono's float handling. The difference in raytracer perf on different .net runtimes is just what brought the poor float handling to his attention. Better mono float handling is a good outcome for lots of non raytracer scenarios. If you read the linked blog about the ray tracer, the C# ports are just blog 3 in a series of 8 that does actually conclude with two posts on SIMD - https://aras-p.info/blog/2018/03/28/Daily-Pathtracer-Part-0-Intro/ https://aras-p.info/blog/2018/03/28/Daily-Pathtracer-Part-0-...
- a_t48 9y agoThis article was about improving floating point performance in general, they just used the benchmark as a benchmark. What correctness are you talking about here? The fact that floats are no longer being promoted to doubles for some operations? It's pretty unnecessary for most things, especially for a game engine.
- vanderZwan 9y agoDid you even read the article? > In Mono, decades ago, we made the mistake of performing all 32-bit float computations as 64-bit floats while still storing the data in 32-bit locations. (...) Applications did pay a heavier price for the extra computation time, but [in the 2003 era] Mono was mostly used for Linux desktop application, serving HTTP pages and some server processes, so floating point performance was never an issue we faced day to day. (...) Nowadays, Games, 3D applications image processing, VR, AR and machine learning have made floating point operations a more common data type in modern applications. When it rains, it pours, and this is no exception. Floats are no longer your friendly data type that you sprinkle in a few places in your code, here and there. They come in an avalanche and there is no place to hide. There are so many of them, and they won’t stop coming at you. The raytracer is just a good performance test.
- nerpderp83 9y agoEarly C compilers made that same mistake.
- slavik81 9y agoIt's the x86 hardware which made the original mistake. Using 80-bit floats in the x87 FPU turned out to be a bad idea. Thankfully, standardizing SSE and SSE2 in x86-64 gave us a way out of that mess.
- bjourne 9y agoYes I did and fwiw, comments asking people whether they read the article or not is ot on hn. A performance test is exactly the same thing as a benchmark. In any real world code, slower floats doesn't matter at all. None of you who have commented have been able to or even tried to prove me wrong on that point.
- vanderZwan 9y ago> In any real world code, slower floats doesn't matter at all. None of you who have commented have been able to or even tried to prove me wrong on that point. First of all, this is Burden of Proof fallacy: the onus is on you to prove this statement right, not on us to prove you wrong. Second of all, nobody has been trying to prove you wrong because you did not actually say that floating point performance does not matter in real world code. You may have had it in mind, but you cannot blame others for not picking up on something you did not communicate in the first place. What you did say was "correctness > speed", which is not the same thing. Furthermore, while this statement is true it needs a context to be applied to, which you have to give. Without further justification by you why using float32 operations for float32 data types would reduce correctness, it is a hollow truism.
- floatboth 9y agoNo, the wrong thing the extra precision they were doing before. When I use a 32-bit type, I absolutely do not expect operations to silently use 64-bit precision by default. Especially considering that other CLR implementations (i.e. Microsoft's original one) do not do this. Least Astonishment > unsolicited extra "correctness".
- aetherspawn 9y agoWow, I hadn’t imagined that because the coordinates are sent to the GPU as floats, that means triangles start voxelizing when you get further away from origin. Seems like it could make an awesome shader-free animation if you translated the entire worlds position by a ridiculously large (increasing in value) float.
- robertAngst 9y agoLet me say that this topic made me realize how crazy some of the problems in programming are. I cant even imagine programming at FB and amazon scales.
- CyberDildonics 9y agoNumerical accuracy of floats and splitting up data into chunks that don't depend on each other are almost as different as any two problems can get.
- workerIbe 9y agoI imagine someone used a float as an index, once.
- __s 9y agoI've dealt with systems using floats as IDs in their DB. Better than when the monetary values were floats
- CyberDildonics 9y agoActually in the CG shader language you can index arrays with floats to get automatic linear interpolation, but I digress...
- kibibu 9y agoTwitter used to use JavaScript numbers to represent various ids in their JSON API. These are, per the JavaScript spec, double-precision (64-bit) floating point numbers. You can only really use these to represent 53-bit integers, so they had to add string versions. (see https://developer.twitter.com/en/docs/basics/twitter-ids https://developer.twitter.com/en/docs/basics/twitter-ids)
- drew-y 9y agoI've run into a similar issue writing a ray tracer in Swift! We are even both using Peter Shirley's "Ray Tracing in One Weekend" as a reference! I'm to this day struggling to get the performance near the level of the C++ reference implementation. I've made some improvements but overall the swift version is around 5x slower. If any one is interested the source code is available here: https://gitlab.com/youngwerth/ray-tracer/settings/repository https://gitlab.com/youngwerth/ray-tracer/settings/repository Compiled using "swift build -c release".
- CyberDildonics 9y agoYou should look at the assembly to know for sure (after you have profiled and narrowed it down). With this sort of speed difference my guess is that there is either excess memory allocation going on, pointer hopping when you think you are using something by value on the stack, or both.
- maxxxxx 9y agoI'll second looking at the assembly code. I had a similar problem a few years ago and an assembly expert told us that we were moving data in and out of the cache all the time instead of leaving it there. We had to change the way we looped through arrays and got a huge improvement. this could be wrong but I would also guess that the Swift optimizer is not as good as the ones C++ has mainly for the reason that it's newer.
- CyberDildonics 9y agoYou don't need to look at assembly to avoid cache misses, you just need to understand what the language is doing under the hood in a general sense, then make sure you access memory in a way that it can be prefetched. My guess is that it is either the program being written slightly differently or that swift is doing some sort of indirection under the hood.
- maxxxxx 9y ago"you just need to understand what the language is doing under the hood in a general sense" Isn't the best to find out to look at the assembly? How else can you know what the compiler and optimizer are doing?
- Retr0spectrum 9y ago"Keanu wonders: is Minecraft chunky purely because everything’s rendered really far from the origin?" Actually, Minecraft used to have some interesting float-precision-induced artifacts once you got far from the origin: https://minecraft.gamepedia.com/Far_Lands https://minecraft.gamepedia.com/Far_Lands
- Amelorate 9y agoMinecraft's Far Lands aren't actually related to floating point precision, although movement near the Far Lands is affected. My understanding of what causes the Far Lands isn't that great, but I think it's caused by one of six or eight shorts overflowing in the generation algorithm. Edit: It seems I needed to read more of the Minecraft Wiki link for the Farlands. https://minecraft.gamepedia.com/Far_Lands#Cause https://minecraft.gamepedia.com/Far_Lands#Cause covers it much better than I could.