簡體   English   中英

修復分布式版本中的算術錯誤

[英]Fix arithmetic error in distributed version

我正在分布式環境中通過 Cholesky 分解來反轉矩陣,正如這里討論的那樣。 我的代碼工作正常,但為了測試我的分布式項目是否產生正確的結果,我不得不將它與串行版本進行比較。 結果並不完全一樣!

例如,結果矩陣的最后五個單元格是:

serial gives:
-250207683.634793 -1353198687.861288 2816966067.598196 -144344843844.616425 323890119928.788757
distributed gives:
-250207683.634692 -1353198687.861386 2816966067.598891 -144344843844.617096 323890119928.788757

我曾在英特爾論壇上發布過關於此的帖子,但我得到的答案是在我將使用分布式版本進行的所有執行中獲得相同的結果,這是我已經擁有的。 他們似乎(在另一個線程中)無法對此做出回應:

如何在串行和分布式執行之間獲得相同的結果? 這可能嗎? 這將導致修正算術錯誤。

我試過設置: mkl_cbwr_set(MKL_CBWR_AVX); 並使用mkl_malloc()來對齊內存,但沒有任何改變。 我將得到相同的結果,只有在我將為分布式版本生成一個進程的情況下(這將使其幾乎是串行的)!

我正在調用的分布式例程: pdpotrf()pdpotri()

我正在調用的串行例程: dpotrf()dpotri()

您的差異似乎出現在第 12 sf 由於浮點算術並不是真正的關聯(即 fp 算術不保證a+(b+c) == (a+b)+c ),並且由於並行執行通常,不會給出操作應用的確定順序,與串行等效項相比,這些微小的差異是並行化數字代碼的典型特征。 實際上,在不同數量的處理器上運行時,您可能會觀察到相同的差異順序,例如 4 對 8。

不幸的是,獲得確定性結果的簡單方法是堅持串行執行。 要從並行執行中獲得確定性的結果,需要付出很大的努力來非常具體地確定直到最后一個+*的操作的執行順序,這幾乎肯定會排除大多數數字庫的使用,並導致您對大型數據進行艱苦的手動編碼數字例程。

在大多數情況下,我遇到的輸入數據(通常來自傳感器)的准確性並不值得擔心第 12 次或以后5th sf 對於所有實際目的來說都是足夠的平等。 對於數學家來說,這是另一回事......

正如另一個答案所提到的,不能保證在串行和分布式之間獲得完全相同的結果。 HPC/分布式工作負載的一種常見技術是驗證解決方案。 從計算錯誤百分比到更復雜的驗證方案,有許多技術,例如HPL 使用的技術 這是一個計算百分比誤差的簡單 C++ 函數。 正如@HighPerformanceMark 在他的帖子中指出的那樣,對這種數值錯誤的分析非常復雜; 這是一種非常簡單的方法,網上有很多關於該主題的信息。

#include <iostream>
#include <cmath>

double calc_error(double a,double x)
{
  return std::abs(x-a)/std::abs(a);
}
int main(void)
{
  double sans[]={-250207683.634793,-1353198687.861288,2816966067.598196,-144344843844.616425, 323890119928.788757};
  double pans[]={-250207683.634692, -1353198687.861386, 2816966067.598891, -144344843844.617096, 323890119928.788757};
  double err[5];
  std::cout<<"Serial Answer,Distributed Answer, Error"<<std::endl;
  for (int it=0; it<5; it++) {
    err[it]=calc_error(sans[it], pans[it]);
    std::cout<<sans[it]<<","<<pans[it]<<","<<err[it]<<"\n";
  }
return 0;
}

產生這個輸出:

Serial Answer,Distributed Answer, Error
-2.50208e+08,-2.50208e+08,4.03665e-13
-1.3532e+09,-1.3532e+09,7.24136e-14
2.81697e+09,2.81697e+09,2.46631e-13
-1.44345e+11,-1.44345e+11,4.65127e-15
3.2389e+11,3.2389e+11,0

正如您所看到的,每種情況下的錯誤數量級都在 10^-13 或更少的數量級上,並且在一種情況下不存在。 根據您嘗試解決這個數量級的錯誤的問題,可以認為是可以接受的。 希望這有助於說明針對串行解決方案驗證分布式解決方案的一種方法,或者至少給出一種方法來顯示並行和串行算法相距多遠。

在驗證大問題和並行算法的答案時,執行並行算法的多次運行,保存每次運行的結果也很有價值。 然后,您可以查看結果和/或錯誤是否隨着並行算法的運行而變化,或者它是否會隨着時間的推移而穩定下來。

表明並行算法在 1000 次運行(僅舉個例子,數據越多對這類事情越好)的可接受閾值內產生各種問題大小的錯誤是評估結果有效性的一種方法。

在過去,當我執行基准測試時,我注意到在服務器“預熱”之前的前幾次運行中的行為變化很大。 當時我從不費心去檢查結果中的錯誤是否會像性能一樣隨着時間的推移而穩定下來,但看到它會很有趣。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM