2016-04-04 22 views
1

iki vektörleri (şamandıra değeri) nokta ürünün farklı makinelerde farklı sonuçlar veren hesaplama:şamandıra boyutları ve çift

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

kodudur:

#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(); 
} 

metin.txt : Ben herhalde

-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 

, bu şekilde şamandıranın büyüklüğüne ve çift bağlıdır ve bu makineler için aynı değildir. Her iki bilgisayar için de aynı çıkışı yapmak mümkün mü?

ben (ilk sonuç 6,102435302 ile) birinci makineye erişimi yok ama (Numpy ile) aşağıdaki python kodu ile aynı sonucu üretebilir:

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

Kodunuzu, giriş ve derleyici ayarlarınızı gönderebilir misiniz? – Micka

+2

Ve senin [mcve] nerede? –

+2

Normalde, son birkaç bitde kayan nokta doğruluğu varsayılan olarak çeşitli derleyici optimizasyon ayarları ile garanti edilemez, ancak değerleriniz _so far_ apart Bu sorunun sorunu olduğunu düşünmüyorum. Kodunuzu gönderin. –

cevap

3

fark kadar büyük double yerine float kullanılarak açıklanmalıdır. Kodunuzdaki gerçek hataları arayın. Ya da hesabınız derece dengesizdir, bu durumda neler olup bittiğini anlayana kadar nelerin olup bittiğini incelemenize gerek yoktur.

Her iki derleyici için de aynı çıktıyı almak kolaydır - sonucu sıfır olarak ayarlamanız yeterlidir. Ama ne istiyorsan sonucu sonucunu elde etmektir. Yanlış bir sonuç, güvenilemeyecek bir sonuç var ve hangisinin hangisi olduğunu bilmiyorsunuz. Sonuçları aynı yapmak sadece bu durumu kapsayacak, ancak herhangi bir problemi çözmeyecektir.

+1

Büyük olasılıkla bu, büyüklükte çok yakın ama kutupsallıkta tersi olan büyük ürün terimlerinin sonucudur. Birleştirildiğinde, göreli hata artar. Bu genellikle, hastalıklı matrislerle de görülür. – doug

+1

@doug: terimlerin hepsi kare olsa da, hepsi olumlu. –

+1

Ah, kod ve verileri eklediğiniz için teşekkürler. Bu oldukça yaygındır. Bir akümülatöre uzun bir sayı listesi eklediğinizde, başlangıç ​​verileri, sondaki verilerden daha doğru bir şekilde eklenir, çünkü akümülatör büyüklükte daha büyük olur. 1.333333 ve .0000333333 eklemeyi düşünün. Veriler, tam makine hassaslığına yuvarlanmış ve kesilmediğinde, ancak kırpılmışsa, daha hızlı eklenmiş bir yanlılık alabilirsiniz. Şamandıraların vektörleri üzerinde işlemler biriktirirken daima bir çift kullanırım. – doug

3

Muhtemelen VS12 otomatik döngüyü vectorized (ve sonra sonucu yanlış yazdıysanız) görünüyor.

sen şekilde vektörleştirilmiş döngü çalıştırırsanız:

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; 
} 

Sonra çıkmak sonucudur:

6,14024353

Bu ama görünüşe 6.102435302 senin ilk sonucu olarak aynıdır transkripsiyon yaparken 4'u kaçırmışsınız gibi.

En azından en iyi açıklaması ile ortaya çıkabilirim. Zaten bu soruda çok uzun süre geçirdim :-)

+0

Makul bir hipoteze yol açan çok güzel bir dedektif çalışması! –