由于使用了更多的内核,Python多处理速度较慢
我正在使用Python多处理模块多次对(大而稀疏)矩阵进行对角化。我必须做上千次,所以决定在多处理中做,因为我有24个核 代码如下所示:由于使用了更多的内核,Python多处理速度较慢,python,numpy,multiprocessing,sparse-matrix,Python,Numpy,Multiprocessing,Sparse Matrix,我正在使用Python多处理模块多次对(大而稀疏)矩阵进行对角化。我必须做上千次,所以决定在多处理中做,因为我有24个核 代码如下所示: import numpy as np from scipy.sparse.linalg import eigsh from scipy import sparse def diag(param): wf, vf = 0, 0 for i in range(10000): num = np.random.rand()
import numpy as np
from scipy.sparse.linalg import eigsh
from scipy import sparse
def diag(param):
wf, vf = 0, 0
for i in range(10000):
num = np.random.rand()
.... # unrelated code producing the matrix with param and num
Mat = sparse.csc_matrix((data, (row, col)), shape=(8000, 8000))
w, v = eigsh(Mat, k=12)
.... #some other unrelated process updating wf and vf using w and v
return wf, vf
def Final(temp):
print("Process " % multiprocessing.current_process().name)
print(temp)
np.random.seed()
w0, v0 = diag(temp)
.... #unrelated process using w0 and v0
if __name__ == '__main__':
with Pool() as p:
print(p.map(Final, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]))
代码的其他部分是不相关的,因为在我的例子中,对8000×8000稀疏矩阵进行对角化是速率决定步骤
当我没有使用多重处理时,这个过程运行得很好。然而,我现在实现多处理的速度与使用的内核数量成反比(!!)。我将非常感谢您在这方面的任何意见,因为我知道池通常会使您的流程(稍微)变慢,但不会降低这么多。我很困惑,因为scipy天生就没有实现多处理
例如。通常在一个内核中,10次对角化大约需要2秒。在24个核中(在上面的示例中为10个核!),需要约40秒
编辑:作为上下文,矩阵非常稀疏-8000 x 8000矩阵中只有48000个条目
编辑:已解决,但仍有剩余问题 我已经解决了这个问题,它非常有趣,我需要你的意见 问题如下:当scipy.sparse对大于某个阈值的矩阵进行对角化时,它会自动执行多线程(我用top进行了检查)。但是,与使用单芯机箱相比,这并没有显著提高速度 我用我自己的笔记本电脑检查了性能(双核,没什么特别的!),性能比24核输出要好(!),24核输出的失败次数稍多,但仍然如此。)并且意识到自动多线程并没有做任何事情,只是建立队列和阻塞多处理
因此,解决方案是使用操作系统将MKL和BLAS设置为单线程,然后设置为多线程,程序现在运行得非常好。我现在很好奇,为什么BLAS首先使用多线程,但根本不使用多线程——这可能是开发人员的问题,但可能还有另一个复杂的解决方案。谁知道呢 多处理意味着复制数据并在完成时将其聚合。这将产生影响。这不是神奇的空闲时间。序列化
wf
和vf
会增加开销,但你正在并行化,所以你会得到一些回报。我不知道您是如何将数据导入分叉流程的,这也可能会减慢您的速度。如果你的内存不足,有10个矩阵副本,你必须交换,我预计会有巨大的性能损失(如你所见)。我不希望你的示例代码运行得那么慢,但魔鬼在细节中没有包括。嗨,谢谢你的回复!我写了一个只涉及矩阵对角化的伪代码。不幸的是,问题依然存在。eigsh代码一直是贪婪的罪魁祸首。我的第一个猜测是可能是GIL,但考虑到多进程是为了避免这个问题,我感到困惑……点头,GIL在这里不太可能是一个猜测,因为正如你所说,这正是多进程要防止的。在进程之间移动时,很可能是序列化/反序列化。正如Mad Physician所说,只有当您的计算非常昂贵,以至于执行多处理的成本超过移动数据的成本时,多处理才有价值(因此数据越大、越难处理,并行化的成本就越高)。也就是说,如果scipy为您尝试执行的计算在C中实现多线程,使用多处理是纯粹的损失;这只会让事情变得更糟,而且永远不会更好,因为多线程根本不需要在进程映像之间复制数据,而在C模块中编写的代码可以在GIL工作时释放GIL,因此,当您开始使用多线程时,每个进程都会启动自己的线程组(这些线程会相互竞争CPU),而且您拥有复制内容所需的所有开销。。