共享多处理阵列的精度损失?

2024-04-24 06:56:45 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在试验多处理数组类型,以便在进程之间共享一个可写对象。我已经阅读了很多关于这样做的注意事项,但是由于物理内存的限制,我相信这在我的应用程序中是必要的。你知道吗

似乎在使用数组时有一些精度上的损失,但是,我不太清楚。下面是一个可重复的示例,它比较了通过多处理数组(带锁)和直接对一系列随机数组求和的结果:

import numpy as np
from joblib import Parallel, delayed
from multiprocessing import Pool, Array 

# Initialize multiprocessing Array and numpy view
n = 100
m = 100
num_reps = 100
arr = Array('d', n*m)
shared_result = np.ctypeslib.as_array(arr.get_obj()).reshape(n,m)

# Function to add random arrays to multiprocessing array
def adder(i,shared_res=shared_result,arr=arr):
    tmp = np.random.rand(n,m)
    with arr.get_lock():
        shared_result[:,:] += tmp
    return tmp

if __name__ == '__main__':
    with Parallel(n_jobs=10) as parallel:       
        tst = parallel(delayed(adder)(k) for k in range(num_reps))

# Compare results from multiprocessing Array vs. explicit sum
print(np.mean(shared_result - sum(tst)))

这将产生:

9.73443547991e-17

而我期望的是0。这里有什么我没有看到的精确性问题吗?你知道吗

更新:问题似乎出在Parallel。如果你不使用它,而是

tst = [adder(k) for k in range(num_reps)]
print(np.mean(np.abs(shared_result - sum(tst))))

正如下面由abarnert建议的,你得到0。那么平行酸洗会降低精度是怎么回事?你知道吗


Tags: fromimportparallelasnp数组resultmultiprocessing
1条回答
网友
1楼 · 发布于 2024-04-24 06:56:45

原始数据的大小是0到1。你的错误是1e-16。你知道吗

这是完全正常的,因为64位浮点数有大约15个有效数字。因此,对于0.5级的计算,预计误差为1e-16。你知道吗

至于为什么使用进程间通信时不会发生错误,可能是因为本地CPU使用80位内部浮点格式(x87一直都是这样),而进程之间发送的浮点数将被限制为64位精度。你知道吗

有一些特殊技术可以更精确地求浮点数集的和。这里有一个:https://en.wikipedia.org/wiki/Kahan_summation_algorithm

相关问题 更多 >