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

时间:2018-07-27 23:09:05

标签: python numpy parallel-processing multiprocessing joblib

我正在尝试使用多处理数组类型在进程之间共享可写对象。我已经阅读了很多有关这样做的警告,但是由于物理内存的限制,我认为在我的应用程序中有必要这样做。

使用Array似乎会导致一些精度损失,但是我不太清楚。这是一个可重现的示例,该示例比较了通过多处理数组(带锁)直接对一系列随机数组求和的结果:

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。那么,在Parallel中进行酸洗会降低精度吗?

1 个答案:

答案 0 :(得分:1)

原始数据的大小为0到1。您的误差约为1e-16。

这完全正常,因为64位浮点数大约有15个有效数字。因此,在进行幅度为0.5的计算时,可能会出现1e-16的误差。

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

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