Deterministik bir modelin çalışmalarında küçük, öngörülemeyen sonuçlar


10

C ile yazılmış büyük bir model (~ 5000 satır) var. Hiçbir yerde rastgele sayı üretimi ile seri bir programdır. FFTW işlevlerini FFTW kullanan işlevler için kullanır - FFTW uygulamasının ayrıntılarını bilmiyorum, ancak buradaki işlevlerin de deterministik olduğunu varsayıyorum (hata yapıyorsam beni düzelt).

Anlayamadığım sorun, aynı makinede (aynı derleyici, aynı kütüphaneler) aynı çalışmaların sonuçlarında küçük farklılıklar alıyorum.

Çift duyarlıklı değişkenler kullanıyorum ve sonucu değişken olarak çıktılamak valueiçin örneğin, sorun: fprintf(outFID, "%.15e\n", value);veya
fwrite(&value, 1, sizeof(double), outFID);

Ve sürekli olarak şu gibi farklılıklar elde
edeceğim : 2.07843469652206 4 e-16 vs. 2.07843469652206 3 e-16

Bunun nedenini anlamaya çalışmak için çok zaman harcadım. Başlangıçta bellek yongalarımdan birinin kötüye gittiğini düşündüm ve boşuna sipariş ettim ve değiştirdim. Daha sonra kodumu bir iş arkadaşının Linux makinesinde çalıştırmayı denedim ve aynı nitelikte farklılıklar elde ediyorum.

Buna ne sebep olabilir? Şimdi küçük bir sorun, ama merak ediyorum (ciddi bir sorunun) "buzdağının ucu".

Sayısal modellerle çalışan birisinin bu sorunla karşılaşması durumunda StackOverflow yerine buraya yazacağımı düşündüm. Eğer birisi buna ışık tutabilirse, çok fazla yükümlü olurdum.

Yorumların
takibi : Christian Clason ve Vikram: ilk olarak soruma gösterdiğiniz ilgi için teşekkür ederim. Aşağıdakileri önermek için bağladığınız makaleler: 1. yuvarlama hataları doğruluğu sınırlar ve 2. farklı kod (görünüşte zararsız yazdırma ifadeleri eklemek gibi) makine epsilonuna kadar sonuçları etkileyebilir. Etkileri fwriteve fprintffonksiyonları kıyaslamadığımı açıklığa kavuşturmalıyım . Birini VEYA diğerini kullanıyorum. Özellikle, her iki çalıştırma için de aynı yürütülebilir dosya kullanılır. Ben fprintfOR kullanmak ister sadece sorunu olduğunu belirten fwrite.

Dolayısıyla kod yolu (ve yürütülebilir) aynıdır ve donanım aynıdır. Tüm bu dış faktörler sabit tutulurken, rastgelelik esasen nereden geliyor? Arızalı hafızanın biraz doğru tutulmaması nedeniyle biraz çevirme olduğundan şüphelendim, bu yüzden bellek yongalarını değiştirdim, ancak buradaki sorun gibi görünmüyor, doğruladım ve siz belirttiniz. Programım, bu çift kesinlikli sayıların binlerceini tek bir çalışmada çıkarır ve her zaman rastgele bit döndürmeleri olan rastgele bir avuç vardır.

Christian Clason ilk yorumuna İzleyen: Neden makine hassasiyet içinde 0 ile aynıdır? Bir çift için en küçük pozitif sayı 2.22e-308'dir, bu yüzden 0'a eşit olmamalıdır? Programım 10 ^ -16 aralığında (1e-15 ila 8e-17 arasında) binlerce değer çıktı ve araştırma projemizde anlamlı varyasyonlar görüyoruz, bu yüzden umarım saçma sapan bakmıyoruz sayılar.210-16

Takip # 2 :
Bu, yorumlardaki offshoot tartışmasına yardımcı olmak için model tarafından üretilen zaman serisi çıktısının bir grafiğidir. resim açıklamasını buraya girin


SciComp.SE'ye hoş geldiniz! Kayan nokta sayılarının sınırlı bir doğruluğa sahip olduğunun farkında mısınız - özellikle, çift hassasiyette, makine hassasiyetine kadar sıfıra eşit olduğunu? Bu nedenle, bildirdiğiniz farklılıklar gerçekten anlamlı değildir ve büyük olasılıkla, adlandırdığınız iki işlevin uygulamalarındaki küçük farklılıklar nedeniyle, biraz farklı makine koduna yol açar. 210-16
Christian Clason

Makinenizin neden makine hassasiyetinden daha doğru olmadığını soruyorsunuz. en.wikipedia.org/wiki/Machine_epsilon
Vikram

1
Kod yollarının kayan nokta aritmetiği üzerindeki ince etkisinin ilgili bir örneği için bkz. İnf.ethz.ch/personal/gander/Heisenberg/paper.html . Ve elbette, ece.uwaterloo.ca/~dwharder/NumericalAnalysis/02Numerics/Double/…
Christian Clason

1
10-16

2
1

Yanıtlar:


9

Modern bilgi işlem sistemlerinin doğası gereği belirleyici olmayan ve bu tür farklılıklara neden olabilecek yönleri vardır. Farklılıklar, çözümlerinizin gerekli doğruluğuna kıyasla çok küçük olduğu sürece, muhtemelen bu konuda endişelenmenize gerek yoktur.

Kendi deneyimlerime dayanarak neyin yanlış gidebileceğine bir örnek. İki x ve y vektörünün nokta çarpımını hesaplama problemini düşünün.

d=Σben=1nxbenyben

xbenyben

Örneğin, önce iki vektörün çarpımını şu şekilde hesaplayabilirsiniz:

d=((x1y1)+(x2y2))+(x3y3)

ve sonra

d=(x1y1)+((x2y2)+(x3y3))

Bu nasıl olabilir? İşte iki olasılık.

  1. Paralel çekirdekler üzerinde çok iş parçacıklı hesaplamalar. Modern bilgisayarlarda genellikle paralel çalışabilen 2, 4, 8 veya daha fazla işlemci çekirdeği bulunur. Kodunuz, bir nokta ürününü birden çok işlemcide hesaplamak için paralel iş parçacıkları kullanıyorsa, sistemin rasgele bozulması (örneğin, kullanıcı faresini hareket ettirdi ve işlemci çekirdeklerinden birinin nokta ürününe dönmeden önce bu fare hareketini işlemesi gerekir) ilavelerin sıralamasında bir değişikliğe yol açar.

  2. Veri ve vektör komutlarının düzenlenmesi. Modern Intel işlemcilerin, aynı anda kayan nokta sayıları için çalışabilecek (örneğin) özel bir talimatlar seti vardır. Veriler 16 bayt sınırlarında hizalanmışsa, bu vektör talimatları en iyi şekilde çalışır. Tipik olarak, bir nokta ürün döngüsü verileri 16 baytlık bölümlere ayırır (her seferinde 4 tane kayar.) Kodu ikinci kez yeniden çalıştırırsanız, veriler 16 bayt bellek bloklarıyla farklı şekilde hizalanabilir, böylece eklemeler farklı bir sırayla, farklı bir cevapla sonuçlanır.

Kodunuzu tek bir iş parçacığı olarak çalıştırarak ve tüm paralel işlemeyi devre dışı bırakarak 1. noktayı adresleyebilirsiniz. Bellek bloklarını hizalamak için bellek ayırma gerektirerek 2. noktayı ele alabilirsiniz (tipik olarak kodu -align gibi bir anahtarla derleyerek yaparsınız.) Kodunuz hala değişen sonuçlar veriyorsa, bakmak için başka olasılıklar da vardır en.

Intel'in bu belgeleri , Intel Math Çekirdek Kütüphanesi ile sonuçların tekrarlanamamasına neden olabilecek sorunları tartışır. Intel'in derleyici anahtarlarını Intel derleyicileriyle kullanmak için tartışan başka bir belge .


Kodunuzun tek iş parçacıklı çalıştığını düşündüğünüzü görüyorum. Muhtemelen kodunuzu iyi bilseniz de, multithreaded çalıştıran alt rutinleri (örneğin BLAS rutinleri) çağırıyor olsaydınız şaşırmazdım. Tam olarak hangi kütüphaneleri kullandığınızı kontrol etmelisiniz. CPU kullanımınızı görmek için sistem izleme araçlarını da kullanabilirsiniz.
Brian Borchers

1
veya belirtildiği gibi FFTW kütüphanesi ...
Christian Clason

@BrianBorchers, teşekkür ederim. Kayan nokta eklemenin çağrışımsal olmayan doğasından gelen rastgelelik örneği aydınlatıcıdır. Christian Clason, sayıların büyüklüğü göz önüne alındığında, model çıktımın anlamlı olup olmadığı konusunda ikincil bir sorun getirdi - haklıysa (ve onu doğru anlıyorum) büyük bir sorun olabilir, bu yüzden şimdi buna bakıyorum.
boxofchalk1

2

Bahsedilen FFTW kütüphanesi belirleyici olmayan bir modda çalışabilir.

FFTW_MEASURE veya FFTW_PATIENT modunu kullanıyorsanız, programlar çalışma zamanında kontrol eder, hangi parametre değerleri en hızlı çalışır ve bu parametreleri tüm program boyunca kullanır. Çalışma süresi açıkça biraz dalgalanacağı için, parametreler farklı olacak ve Fourier dönüşümlerinin sonucu belirleyici olmayacaktır. Deterministik FFTW istiyorsanız, FFTW_ESTIMATE modunu kullanın.


1

Çok çekirdekli / çok iş parçacıklı işleme senaryoları nedeniyle ifade terimi değerlendirme sırası değişikliklerinin çok iyi gerçekleşebileceği doğru olsa da, (uzun bir çekim olmasına rağmen) iş yerinde bir tür donanım tasarımı kusuru olabileceğini unutmayın. Pentium FDIV problemini hatırlıyor musunuz? (Bkz. Https://en.wikipedia.org/wiki/Pentium_FDIV_bug ). Bir süre önce, pc tabanlı analog devre simülasyon yazılımı üzerinde çalıştım. Metodolojimizin bir kısmı, yazılımın gece yapılarına karşı çalışacağımız regresyon testi paketlerini geliştirmeyi içeriyordu. Geliştirdiğimiz birçok modelle, yinelemeli yöntemler (örneğin, Newton-Raphson ( https://en.wikipedia.org/wiki/Newton%27s_method) ve Runge-Kutta) simülasyon algoritmalarında yaygın olarak kullanılmıştır. Analog cihazlarda, voltajlar, akımlar vb. Gibi dahili yapaylıkların son derece küçük sayısal değerlere sahip olması sıklıkla görülür. Simülasyon sürecinin bir parçası olan bu değerler, (simüle edilmiş) zaman içinde kademeli olarak değişir. Bu değişikliklerin büyüklüğü son derece küçük olabilir ve sık sık gözlemlediğimiz, bu tür delta değerleri üzerindeki sonraki FPU işlemlerinin FPU'nun hassasiyetinin "gürültü" eşiğinde (64-bit yüzmede 53-bit mantis, IIRC vardır) olmasıdır. Bu, sık sık hata ayıklama (ah, iyi ol 'gün!), Günlük olarak pratik garantili sporadik sonuçlar sağlamak için modellere sık sık "PrintF" günlük kodunu tanıtmak zorunda olduğu gerçeği ile birleştiğinde! Ne olmuş yani' Bütün bunlar ne demek? Bu koşullar altında farklılıkları görmeyi beklemelisiniz ve yapılacak en iyi şey, bunları ne zaman göz ardı edeceğinize / nasıl göz ardı edeceğinize karar vermenin bir yolunu (büyüklük, frekans, eğilim vb.) Tanımlamak ve uygulamaktır.


İçgörü için teşekkürler Jim. Hangi temel olguların bu tür "içsel yapaylıklara" neden olacağına dair herhangi bir fikir var mı? Elektromanyetik girişimin bir tane olabileceğini düşündüm, ama sonra önemli bitler de etkilenecekti, değil mi?
boxofchalk1

1

Asenkron işlemlerden kayan nokta yuvarlama söz konusu olsa da, bunun daha banal bir şey olduğundan şüpheleniyorum. Aksi halde deterministik kodunuza rastgele bir özellik ekleyen başlatılmamış değişken kullanımı. Hata ayıklama modunda çalıştırdığınızda tüm değişkenler bildirimde 0 olarak başlatıldığından, genellikle geliştiriciler tarafından gözden kaçan yaygın bir sorundur. Hata ayıklama modunda çalışmadığında, bir değişkene atanan bellek, atamadan önce belleğin sahip olduğu değere sahiptir. Bellek, optimizasyon olarak atamada sıfırlanmaz. Kodunuzda bu oluyorsa, kütüphaneler kodunda daha az düzeltilmesi kolay olacaktır.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.