KTBFFH
KTBFFH

Reputation: 65

Size of float and double

Calculating the dot-product of two vectors (float value) gives the different results on the different machines:

6.102435302 (Win7 x64, compiler VS12 version 17.00.50727.1)
6.140244007 (Win7 x64, MinGW, gcc version 5.3.0)

The code is:

#include <iostream>
#include <iterator>
#include <fstream>
#include <vector>
#include <iomanip>
#include <algorithm> 

int main(int argc, char** argv){

std::ifstream is("test.txt");
std::istream_iterator<float> start(is), end;
std::vector<float> numbers(start, end);
std::cout << "Read " << numbers.size() << " numbers" << std::endl;

float product = 0;
for (int i = 0; i <= numbers.size() - 1; i++)
    product += (numbers[i])*(numbers[i]); // += means add to product
std::cout << std::setprecision(10) << product << std::endl;

std::cin.get();
}

test.txt is:

-0.082833 
0.151422 
-0.088526 
-0.538506 
0.646273 
0.266993 
0.200206 
-0.149989 
0.141407 
0.158835 
-0.119255 
-0.039122 
-0.045419 
0.141848 
-0.218912 
-0.264521 
0.032238 
-0.055877 
0.100393 
-0.097075 
-0.006268 
-0.070172 
-0.275793 
0.103654 
-0.075405 
-0.117017 
0.029951 
-0.094158 
-0.168427 
0.381314 
0.144073 
-0.100971 
-0.078645 
0.013768 
0.144876 
0.005855 
-0.018223 
-0.090576 
-0.071564 
-0.029456 
-0.098014 
-0.149181 
0.200667 
-0.189492 
0.264529 
-0.061738 
-0.097826 
0.138872 
-0.241878 
0.019428 
-0.087634 
-0.058300 
-0.009269 
0.039241 
-0.066350 
0.059845 
-0.048516 
-0.070653 
-0.116227 
0.037203 
-0.037091 
-0.097324 
0.043834 
-0.340037 
0.133938 
0.087197 
0.213261 
-0.170708 
-0.151203 
0.052959 
0.027145 
-0.142675 
-0.209020 
0.001813 
-0.022321 
0.190862 
-0.015501 
-0.228589 
-0.038538 
-0.038480 
-0.194482 
0.087518 
-0.257362 
0.160805 
-0.114158 
0.176832 
0.219573 
-0.333160 
-0.068385 
-0.143289 
-0.228401 
0.214679 
0.277186 
-0.130965 
0.142526 
-0.166073 
-0.035309 
0.001260 
-0.064977 
0.020747 
0.014043 
-0.133625 
-0.156975 
-0.043092 
0.154749 
-0.181473 
-0.288339 
-0.144132 
-0.004081 
-0.071694 
-0.094631 
0.483994 
-0.260140 
0.020749 
0.031850 
0.041064 
0.250101 
-0.192338 
-0.222687 
0.114226 
-0.227428 
0.005388 
-0.163509 
-0.135427 
-0.206788 
-0.021093 
0.279840 
-0.055362 
-0.016305 
-0.279524 
0.277402 
0.198076 
0.103796 
-0.272994 
0.306518 
-0.024435 
0.149532 
-0.165079 
-0.394348 
-0.141590 
-0.188541 
0.002890 
0.064264 
-0.045430 
-0.026021 
0.096325 
0.033765 
0.111890 
-0.012204 
0.130457 
-0.106022 
-0.180052 
-0.447620 
0.051825 
0.089245 
-0.265819 
-0.087720 
0.180074 
-0.259521 
-0.356145 
0.162247 
0.282323 
-0.096935 
-0.040101 
-0.214359 
0.357032 
0.195393 
0.150603 
-0.120796 
0.204032 
0.130334 
0.115753 
-0.123727 
-0.107526 
0.196002 
-0.397541 
0.320854 
0.013272 
-0.058865 
0.018108 
0.023616 
-0.053654 
-0.223593 
-0.310052 
0.109229 
-0.107124 
0.074454 
-0.021471 
-0.033081 
0.108072 
-0.067013 
-0.084968 
-0.171947 
0.308421 
-0.204827 
-0.060015 
0.092264 
0.115863 
0.131043 
0.041844

I suppose, it somehow depends on the size of float and double and they are not the same for these machines. Is it possible to make the same output for both computers?

I have no access to the first machine (with the first result 6.102435302), but I can reproduce the same result with the following python code (with numpy):

test = np.loadtxt(test_file, dtype=np.float32)
result = test.dot(test)

Upvotes: 1

Views: 414

Answers (2)

Mike Vine
Mike Vine

Reputation: 9837

It looks likely that the VS12 auto vectorized the loop (and then you mis-typed the result).

If you run the loop vectorised as so:

float product = 0;
for (int i = 0; i < numbers.size(); i+= 4)
{
    __m128 val = *(__m128*)(&numbers[i]);
    auto res = _mm_dp_ps (val, val, 255);
    float result;
    _mm_store_ss(&result, res);

    product += result;
}

Then the result you get out is:

6.14024353

This is the same as your first result of 6.102435302 but it looks like you missed the 4 out whilst transcribing.

At least the the best explanation I can come up with. Already spent way too long on this question :-)

Upvotes: 3

gnasher729
gnasher729

Reputation: 52530

The difference is too large to be explained by using float instead of double. Look for actual bugs in your code. Or your calculation is highly unstable, in which case you really need to examine what's going on and can't trust any numbers until you understood what's going on.

Getting the same output for both compilers is easy - just set the result to zero. But what you want is to get the correct result. You have one result that is badly wrong, and one that cannot be trusted, and you don't know which one is which. Making the results the same would only cover this up but not solve any problem.

Upvotes: 3

Related Questions