我在分布式环境中通过 Cholesky 分解来反转矩阵,正如所讨论的那样 here .我的代码运行良好,但为了测试我的分布式项目是否产生正确的结果,我不得不将它与串行版本进行比较。结果不完全一样!
例如,结果矩阵的最后五个单元格是:
serial gives:
-250207683.634793 -1353198687.861288 2816966067.598196 -144344843844.616425 323890119928.788757
distributed gives:
-250207683.634692 -1353198687.861386 2816966067.598891 -144344843844.617096 323890119928.788757
我在 Intel forum 发过帖子关于这一点,但我得到的答案是在我将使用分布式版本进行的所有执行中获得相同的结果,这是我已经拥有的。他们似乎(在另一个线程中)无法对此做出回应:
如何在串行和分布式执行之间获得相同的结果?这可能吗?这将导致修正算术错误。
我试过这样设置:mkl_cbwr_set(MKL_CBWR_AVX);
并使用 mkl_malloc()
来对齐内存,但没有任何改变。我将得到相同的结果,只是在我将为分布式版本生成一个进程(这将使它几乎是串行的)的情况下!
最佳答案
你的分歧似乎出现在大约 12 s.f.由于浮点运算不是真正的关联(即,f-p 运算不保证 a+(b+c) == (a+b)+c
),并且由于并行执行不保证,通常,给出操作应用的确定顺序,与串行等效代码相比,这些小差异是并行数字代码的典型特征。事实上,当在不同数量的处理器上运行时,您可能会观察到相同顺序的差异,比如 4 对 8。
不幸的是,获得确定性结果的简单方法是坚持串行执行。要从并行执行中获得确定性结果,需要付出巨大努力才能非常具体地确定操作的执行顺序,直到最后一个 +
或 *
,这几乎肯定会排除使用大多数数字库,并引导您对大型数字例程进行艰苦的手动编码。
在我遇到的大多数情况下,输入数据的准确性(通常来自传感器)并不需要担心第 12 次或更晚的 s.f.我不知道你的数字代表什么,但对于许多科学家和工程师来说,等于第 4 或第 5 个 sf 对于所有实际目的来说已经足够了。这对数学家来说是另一回事......
关于c++ - 修复分布式版本中的算术错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32074644/