4 ms·
> It seems have nothing to do with speed of computation, difference in speed caused by formatting inside snprintf Both the versions have snprintf. Please share
by apjana 7y ago
> It seems have nothing to do with speed of computation, difference in speed caused by formatting inside snprintf
Both the versions have snprintf. Please share your numbers without snprintf.
- ordu 7y ago> Both the versions have snprintf. Yes, but with different format strings. It is obvious isn't it? There are just 2 FPU operations in coolsize_f, while coolsize_i have a bunch of 'if'. It just cannot be that the speed difference is due to FPU operations. It must be somewhere in snprintf. But if you asked, I tried to test my assumptions. tl;dr: - seems that measuring is wrong somehow - in any case formatting in snprinf is much slower than calculations itself Numbers for test "as is" are: Timing 500000 iterations F time 0.151318 I time 0.064491 Then I changed: - snprintf(size_buf, 12, "%.*Lf%c", i, size + rem * div_2_pow_10, U[i]); + snprintf(size_buf, 12, "%" PRId64 "%c", size + rem * div_2_pow_10, U[i]); This way I just replaced floating point formatting, with integer formatting. It broke all tests of course, but it doesn't matter for our test: all the calculations are the same and we are measuring them. The numbers are: Timing 500000 iterations F time 0.056365 I time 0.064846 Now coolsize_f is faster. But it somehow strange, because I expected coolsize_f to be even more faster in this case (coolsize_i conditionally uses longer format string). Then I removed all the snprintfs (in case of coolsize_f I just commented them out with FPU operations; in case of coolsize_i I commented out the if around snprintf): Timing 500000 iterations F time 0.012604 I time 0.007449 Now coolsize_f has just while-loop, and coolsize_i has this loop and a bunch of 'if's. But coolsize_f is slower, wtf? I did look closer and found one difference between loops: if (rem >= 512) ++size; Seems it is a costly operation when inside of loop. But then I hit a strangeness. I tried to make coolsize_f to show the same timings as coolsize_i or lower. I removed this 'if' inside of 'while', I discovered that type of rem is long double (so it was converted to int for bitwise & and then back to long double?) and changed it to int. And nevertheless I see the difference: Timing 500000 iterations F time 0.010668 I time 0.007448 WTF? I changes the order of tests in test_relative_speed, so the coolsize_i tested before coolsize_f: srand48(17); gettimeofday(&t0, NULL); for(i = 0; i < n; i++) coolsize_i(lrand48()); gettimeofday(&t1, NULL); timediff(&ti, &t1, &t0); srand48(17); gettimeofday(&t0, NULL); for(i = 0; i < n; i++) coolsize_f(lrand48()); gettimeofday(&t1, NULL); timediff(&tf, &t1, &t0); and viola: Timing 500000 iterations F time 0.006025 I time 0.011848 I don't know how to explain it. n seems to be large enough to make any caching effects to be small and insignificant. Maybe it has something to do with compilator being too clever and removing "useless" code? But why the changing of order of time measures makes any difference? It needs more testing. edit: formatting
- apjana 7y agoVery interesting indeed! If you can come up with a faster and accurate floating point alternative do raise a PR by all means. Many thanks for running the tests and sharing the results!
- apjana 7y agoYes, even I ran the tests and noticed printing the double in snprintf() is the bottleneck Any idea how we can do that faster and we get the format we need in `nnn`?
- apjana 7y agoTiming 500000 iterations F time 0.006025 I time 0.011848 Expected, right? First you called `coolsize_i(lrand48())` and then `coolsize_f(lrand48())`? In your results F should be I and I should be F. In all your tests the F version is slower, as per my expectation.