-1

我有一个包含大量 N 的 32 位浮点数的文件。该文件是使用 numpys 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 和 CI 中评估样条曲线时,得到不同的值。

4

1 回答 1

0

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

不它不是。您已经对“大量”单精度浮点值求和,因此它不太可能精确到超过四位或五位有效数字,尤其是在值的动态范围很大的情况下。

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

于 2017-07-03T12:42:09.283 回答