2

我在分布式环境中通过 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()

4

2 回答 2

4

您的差异似乎出现在大约 12 sf 由于浮点算术不是真正的关联(即 fp 算术不保证a+(b+c) == (a+b)+c),并且由于并行执行通常不会给出操作应用的确定性顺序,与串行等效代码相比,这些微小的差异是并行数字代码的典型特征。实际上,当在不同数量的处理器上运行时,您可能会观察到相同的差异顺序,例如 4 对 8。

不幸的是,获得确定性结果的简单方法是坚持串行执行。要从并行执行中获得确定性的结果,需要付出很大的努力来非常具体地确定操作的执行顺序,直到最后一个+,或者*几乎可以肯定地排除了大多数数字库的使用,并导致您对大型数字例程进行艰苦的手动编码.

在大多数情况下,我遇到的输入数据的准确性,通常来自传感器,不需要担心 12 号或以后的 sf 我不知道你的数字代表什么,但对于许多科学家和工程师来说,等于 4 号或5th sf 对于所有实际目的来说已经足够平等了。这对数学家来说是另一回事......

于 2015-08-18T14:16:25.723 回答
2

正如另一个答案提到的那样,不能保证在串行和分布式之间获得完全相同的结果。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 次运行的可接受阈值内产生错误(只是一个示例,此类事情的数据越多越好)是评估结果有效性的一种方法。

过去,当我执行基准测试时,我注意到在服务器“热身”之前的前几次运行的行为差异很大。当时我从不费心检查结果中的错误是否会像性能一样随着时间的推移而稳定,但看看会很有趣。

于 2015-08-18T15:39:34.597 回答