5 ms·
"just use doubles" Okay, and all of the data that I send off to my GPU for either computation or rendering - I should just accept the huge performance hit I ge
by RogerL 13y ago
"just use doubles"
Okay, and all of the data that I send off to my GPU for either computation or rendering - I should just accept the huge performance hit I get when using double on them?
Or I am up against the cache limits - I should just make everything double and accept that my code now thrashes as the CPU's cache misses?
Sorry, that probably comes off as antagonistic. But this is not a 'just do X' situation. Those of us that do heavy computation tend to think about this a lot, if it was as trivial/cost-free as changing float to double we would have done that already.
- pcwalton 13y agoWhat I mean is that if you want to do 64-bit math on 32-bit values, convert them to 64-bit first. (This matches what the compiler frontend is inserting into the IR and assembly anyway.) Not "use 64 bit everywhere".
- acqq 13y agoTo provide meaningful results, 64-bit math should be implicit, 32-bit explicit. The reason is: just like you believe that "it's same" or "it's not important" (it's not the same and it is very often actually important) there are a lot of programmers who don't want to spend any energy in "making the computer doing what's right" they simply assume that the computer "does what's right." In your language case, if it's hard to have 64-bit partial results, the programmers won't do this where they should. And the proper computations are the serious thing. Like calculating if the bridge will fall or not.
- pcwalton 13y agoOK, so we agree that this is serious, and we need to make sure that programmers understand whether 32-bit or 64-bit arithmetic is being performed, lest the bridge collapses. In Rust a programmer familiar with the rules would write it this way, making it clear what's happening: bridge.d = (bridge.a as f64 * bridge.b as f64 + bridge.c as f64) as f32; Taking advantage of the implicit conversions, a programmer familiar with C++'s rules might write: bridge.d = bridge.a * bridge.b + bridge.c; Now suppose that, years later, someone comes along and wants to refactor the code by adding a temporary. In Rust: let tmp = bridge.a as f64 * bridge.b as f64; bridge.d = (tmp + bridge.c as f64) as f32; In C++: auto tmp = bridge.a * bridge.b; bridge.d = tmp + bridge.c; And now they've changed the meaning of the code in a serious way, because adding a temporary silently changes the meaning of the code.
- acqq 13y agoIt seems you missed something: auto tmp = bridge.a * bridge.b; The type of the right hand expression is 64-bit FP by definition we discuss, so "auto" means "double" in your example. Only if you do simple assignment the type remains 32-bit, every "+" "-" "*" etc promotes it to 64. It can actually be implemented in your language too and the rest of the compiler will keep functioning.
- pcwalton 13y ago#include <stdio.h> int main() { float a = 1.0f; float b = 2.0f; auto c = a + b; printf("%lu\n", sizeof(c)); return 0; } $ clang++ test.cpp $ ./a.out 4 This is a perfect example of how C++'s floating point conversion rules are so complex nobody knows them!
- acqq 13y agoHave you tried float a = 1, b = 7; auto c = a / b? It should give you 8 (I don't have clang here). Note that in the example you constructed you have practically a constant which doesn't lose precision by staying as 32 bits? Have you also checked compiler options that affect the computations? The proper numerics is sometimes (often!) not default, but C and C++ compilers are not "one size fits all."
- pcwalton 13y agoTried that, also in -std=c++11 mode, still 4… Edit: By default clang++ has FLT_EVAL_METHOD set to 0 (i.e. Rust's behavior). When I tried with -mno-sse FLT_EVAL_METHOD was set to 2 (long double promotion), but the sizeof was still 4.
- dllthomas 13y agog++ seems to duplicate your clang results, for the record (as more or less expected).
- 13y ago
- Teckla 13y agoOkay, and all of the data that I send off to my GPU for either computation or rendering - I should just accept the huge performance hit I get when using double on them? When necessary, manually cast your floats to doubles, perform the calculation, then assign the result back to a float. It achieves the same thing, though it is, of course, verbose. For example: float result = (float) ((double) floatVar1 + (double) floatVar2);
- acqq 13y agoYou obviously don't have to write numerical code. I also guess, if you had to, you'd also be fast to start avoiding language that forces you to do the above dance everywhere.
- Teckla 13y agoYou obviously don't have to write numerical code. I also guess, if you had to, you'd also be fast to start avoiding language that forces you to do the above dance everywhere. I didn't claim it would be pretty, I was just demonstrating that it's possible.