Matlab linspace和范围与Kahan求和算法的准确性

时间:2013-04-19 08:55:48

标签: matlab parallel-processing floating-point vectorization double-precision

我正在使用Matlab linspace函数和范围:运算符来获得等间距的向量,但我无疑会收到不等间距的数字。我的代码如下:

format long

x1 = linspace(3,5,20);
diff(x1)

x2 = 3:0.1:5;
diff(x2)

并且向量差异(diff)的输出如下:

x1    
0.105263157894737   
0.105263157894737   
0.105263157894737   
0.105263157894737
0.105263157894737
0.105263157894737
0.105263157894737   
0.105263157894737
0.105263157894737   
0.105263157894737   
0.105263157894737   
0.105263157894737
0.105263157894736   
0.105263157894737   
0.105263157894737   
0.105263157894736
0.105263157894737   
0.105263157894736   
0.105263157894737

x2
0.100000000000000   
0.100000000000000   
0.100000000000000   
0.100000000000000
0.100000000000000   
0.100000000000000   
0.100000000000000   
0.100000000000000
0.100000000000000   
0.100000000000000   
0.100000000000000   
0.100000000000001
0.100000000000000   
0.100000000000001   
0.100000000000000   
0.100000000000000
0.100000000000001   
0.100000000000000   
0.100000000000001   
0.100000000000000

为了解决这个问题,我通过以下代码使用Kahan求和方法:

dx = 2/19;
x3 = zeros(size(x1));
x3(1) = 0;
partial_sum = 0;
c = 0.0;
for k=2:20,
    y = dx - c;
    t = partial_sum + y;
    c = (t - partial_sum) - y;
    partial_sum = t;
    x3(k) = partial_sum;
end
diff(x3)

我现在正在获得一个等间距矢量

0.105263157894737   
0.105263157894737   
0.105263157894737   
0.105263157894737
0.105263157894737   
0.105263157894737   
0.105263157894737   
0.105263157894737
0.105263157894737   
0.105263157894737   
0.105263157894737   
0.105263157894737
0.105263157894737   
0.105263157894737   
0.105263157894737   
0.105263157894737
0.105263157894737   
0.105263157894737   
0.105263157894737

然而,这种方法是“顺序的”。是否有人知道Kahan求和方法的矢量化或并行实现,以提高效率或将其移植到(CUDA)并行缩减?

提前谢谢你。

2 个答案:

答案 0 :(得分:4)

我认为你是误会

(a) linspace的使用。你的电话

linspace(3,5,20)

返回20个等间距的数字,从3开始,到5结束。尝试

linspace(3,5,21)

代替。请注意,向量xx2的长度相差一个。

(b)

浮点运算的微妙之处。这个主题在SO上被广泛讨论,我不会重现已经找到的许多好的解释。

我认为您所看到的是数字,这些数字对于大多数数字应用而言等间距

答案 1 :(得分:3)

我想这个链接会有所帮助:

http://www.mathworks.com/matlabcentral/fileexchange/26800

您将找到XSum函数,您可以在其中切换和测试不同的求和方法:

  • Double:Matlab的SUM的线程安全实现。至少在Matlab 2008a到2009b中,多线程SUM的结果可能与呼叫之间略有不同。比单线程SUM(MSVC ++ 2008)快50%,等效精度。
  • Long:如果编译器支持这个(例如LCC v3.8),则在80位长的double中累计。 3.5更多有效数字,慢40%。
  • Kahan:从下一个元素中减去本地错误。 1到3个有效数字,慢10%。
  • Knuth:好像总和是在128位浮点数中累计的:大约15个有效数字。大约相同的速度(MSVC ++ 2008编译器)。这适用于最现实世界的问题。
  • Knuth2:30个有效数字,就像它在196位浮点数中累积一样。慢了60%。
  • KnuthLong:作为Knuth,但如果编译器支持,则使用long double来获得大约21个有效数字。慢了2.5倍。