Numpy矩阵乘法在多处理池中给出的结果略有不同



我想并行计算函数的数值梯度。然而,我意识到在多处理池中评估函数会得到与以前不同的结果。看起来矩阵乘法是不同的。我在下面的代码中重新构造了这个问题。对于较小的矩阵大小,如(5,2(,结果是等价的。我使用的是Python 3.7.4和Numpy 1.18.5。对于较大的矩阵,有没有一种方法可以得到等效的结果?

import numpy as np
import multiprocessing as mp
import os
def setNumSubLibraryThreads(n):
os.environ["OMP_NUM_THREADS"] = str(n)
os.environ["OPENBLAS_NUM_THREADS"] = str(n)
os.environ["MKL_NUM_THREADS"] = str(n)
os.environ["VECLIB_MAXIMUM_THREADS"] = str(n)
os.environ["NUMEXPR_NUM_THREADS"] = str(n)

def solveInParallel(f, args):
cpu_count = mp.cpu_count()
setNumSubLibraryThreads(1)
p = mp.Pool(cpu_count)
sol = np.array(p.map(f,args))
p.close()
setNumSubLibraryThreads(cpu_count)
return sol
def g(args):
mat1, mat2 = args
return mat1.T.dot(mat2)
if __name__ == '__main__':
np.random.seed(42)
mat1 = np.random.random((1000,20))
mat2 = np.random.random((1000,20))
ref = mat1.T.dot(mat2)
res_par_mat = solveInParallel(g, [(mat1, mat2)])
print(res_par_mat[0] == ref)
np.__config__.show() gives                                                                                                                            
blas_mkl_info:
NOT AVAILABLE
blis_info:
NOT AVAILABLE
openblas_info:
libraries = ['openblas', 'openblas']
library_dirs = ['...']
language = c
define_macros = [('HAVE_CBLAS', None)]
blas_opt_info:
libraries = ['openblas', 'openblas']
library_dirs = [...]
language = c
define_macros = [('HAVE_CBLAS', None)]
lapack_mkl_info:
NOT AVAILABLE
openblas_lapack_info:
libraries = ['openblas', 'openblas']
library_dirs = [...]
language = c
define_macros = [('HAVE_CBLAS', None)]
lapack_opt_info:
libraries = ['openblas', 'openblas']
library_dirs = [...]
language = c
define_macros = [('HAVE_CBLAS', None)]

我似乎不得不接受那个舍入错误。

import numpy as np
import multiprocessing as mp
from threadpoolctl import threadpool_limits

def solveInParallel(f, args):
cpu_count = mp.cpu_count()
with threadpool_limits(limits=1, user_api='blas'):
p = mp.Pool(cpu_count)
sol = np.array(p.map(f,args))
p.close()
return sol
def g2(args):
mat1, mat2 = args
return mat1.T.dot(mat2)
if __name__ == '__main__':
np.random.seed(42)
mat1 = np.random.random((1000,20))
mat2 = np.random.random((1000,20))
ref = mat1.T.dot(mat2)
res = solveInParallel(g2, [(mat1, mat2)])
print(res[0]== ref)

最新更新