2017-07-03 110 views
-1

我有一个包含32位浮点数N的大文件。此文件是使用numpys MEMMAP功能如下创建:C mmap和numpy memmap之间的差异

mmoutput = np.memmap("filename", dtype='f4', mode='w+', offset=0, shape=N) 
mmoutput[:] = my_floats 
mmoutput.flush() 

当我使用numpy的加载这些系数回来,并使用它们求和:

mminput = np.memmap("filename", dtype="f4", mode='c', offset=0, shape=N) 
mminput.sum() 

我得到的值82435.047(这是正确的)。

然而,当我用C的MMAP如下的彩车阅读:

int fd = open("filename", O_RDONLY, 0); 
float * coefs = (float*) mmap(NULL, sizeof(float) * N, PROT_READ, MAP_SHARED, fd, 0); 
double sum = 0.0; 
for (int i = 0; i < N; i++) sum += coefs[i]; 

的数字之和为不同的值:82435.100。

有人可以帮我发现我的错误吗?或许numpy写它的浮动和C读取它们的方式有区别吗?

全面披露

我其实是只计算这些数字的总和作为检查它们是相同的。它们的实际用途是作为bspline中的系数(使用如图所示的einspline库实现,例如,在这里为https://github.com/ahay/src/blob/master/user/cram/esc_slow2.c)。当我评估python和C中的样条曲线时,我会得到不同的值。

+0

您的示例中没有求和代码。 –

+0

公平点 - 现在加入 – JMzance

+0

@JMzance同时显示如何在开始之前将'sum'设置为0。 – unwind

回答

0

我得到值82435.047(这是正确的)。

不,它不是。您已经总结出了大量的单精度浮点值,因此不可能精确到超过四位或五位有效数字,特别是如果值的动态范围很大。

我怀疑numpy正在执行一个提高精度的总和,例如转换为双精度。 source通过几次调用umath.add.reduce跟踪,然后我迷路了,所以它可能会以双精度进行求和。尝试转换为双打或使用Kahan summation得到一个不会失去精度的结果 - Kahan会给出比任何加法减少更准确的结果,因为它对动态范围效应进行了修正。

+0

当我使用double sum = 0.0而不是浮点数时,总和得到了改善。然而,价值仍然不同,尽管数量较少。当我将这些值赋给bspline并对它进行评估时,结果会不同 – JMzance

+0

@JMzance如果你想得到完全相同的结果,可以使用与numpy相同的实现策略和优化。但是,如果您的应用程序需要6位有效数字,那么您不应该将数据放在浮点数上,因为每次操作都会失去精度。那么,您的目标是确保numpy和简单的C代码的行为方式完全相同,或试图获得“这些值的总和是多少”的答案? –

+0

前者 - 我需要将相同的单精度浮点数传递给einspline以用作系数。我不介意,只要从文件中读取完全相同的内容,它们就可以归结为不同的东西 – JMzance