介绍
Kahan 求和/补偿求和是解决编译器无法尊重数字关联属性的技术。截断误差导致 (a+b)+c 不完全等于 a+(b+c),从而在较长的和序列上累积不希望的相对误差,这是科学计算中的常见障碍。
任务
我希望 Kahan 求和的最佳实现。我怀疑使用手工汇编代码可以实现最佳性能。
尝试
下面的代码使用三种方法计算 [0,1] 范围内的 1000 个随机数的总和。
标准求和:累积均方根相对误差的朴素实现,其增长为 O(sqrt(N))
Kahan summation [g++]:使用 c/c++ 函数“csum”进行补偿求和。评论中的解释。请注意,某些编译器可能具有使此实现无效的默认标志(请参见下面的输出)。
Kahan summation [asm]:使用与“csum”相同的算法实现为“csumasm”的补偿求和。评论中的神秘解释。
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
extern "C" void csumasm(double&, double, double&);
__asm__(
"csumasm:\n"
"movsd (%rcx), %xmm0\n" //xmm0 = a
"subsd (%r8), %xmm1\n" //xmm1 - r8 (c) | y = b-c
"movapd %xmm0, %xmm2\n"
"addsd %xmm1, %xmm2\n" //xmm2 + xmm1 (y) | b = a+y
"movapd %xmm2, %xmm3\n"
"subsd %xmm0, %xmm3\n" …Run Code Online (Sandbox Code Playgroud)