用joblib实现Python循环并行化

用joblib实现Python循环并行化,python,numpy,parallel-processing,joblib,Python,Numpy,Parallel Processing,Joblib,我希望得到一些帮助,以准确理解我所做的工作/为什么我的代码没有像我期望的那样运行 我已经开始使用joblib来尝试通过并行运行(大型)循环来加速代码 我是这样使用它的: from joblib import Parallel, delayed def frame(indeces, image_pad, m): XY_Patches = np.float32(image_pad[indeces[0]:indeces[0]+m, indeces[1]:indeces[1]+m, inde

我希望得到一些帮助,以准确理解我所做的工作/为什么我的代码没有像我期望的那样运行

我已经开始使用joblib来尝试通过并行运行(大型)循环来加速代码

我是这样使用它的:

from joblib import Parallel, delayed
def frame(indeces, image_pad, m):

    XY_Patches = np.float32(image_pad[indeces[0]:indeces[0]+m, indeces[1]:indeces[1]+m,  indeces[2]])
    XZ_Patches = np.float32(image_pad[indeces[0]:indeces[0]+m, indeces[1],                  indeces[2]:indeces[2]+m])
    YZ_Patches = np.float32(image_pad[indeces[0],                 indeces[1]:indeces[1]+m,  indeces[2]:indeces[2]+m])

    return XY_Patches, XZ_Patches, YZ_Patches


def Patch_triplanar_para(image_path, patch_size):

    Image, Label, indeces =  Sampling(image_path)

    n = (patch_size -1)/2
    m = patch_size

    image_pad = np.pad(Image, pad_width=n, mode='constant', constant_values = 0)

    A = Parallel(n_jobs= 1)(delayed(frame)(i, image_pad, m) for i in indeces)
    A = np.array(A)
    Label = np.float32(Label.reshape(len(Label), 1))
    R, T, Y =  np.hsplit(A, 3)

    return R, T, Y, Label
我一直在尝试“n_jobs”,希望增加它可以加快我的功能。然而,随着我增加n_工作岗位,事情会明显放缓。在没有“并行”的情况下运行此代码时,速度会变慢,直到我将作业数从1增加到1为止

为什么会这样?我知道我运行的作业越多,脚本速度就越快?我用错了吗


谢谢

您的问题可能是因为
image\u pad
是一个大数组。在代码中,您使用的是
joblib
的默认
multiprocessing
后端。这个后端创建了一个worker池,每个worker池都是一个Python进程。然后将函数的输入数据复制
n_jobs
次,并广播给池中的每个工作者,这可能会导致严重的开销。引用客户的文档:

默认情况下,当n_jobs!=1.作为并行调用的输入传递的参数被序列化并重新分配到每个工作进程的内存中

这对于大型争论来说可能是个问题,因为工人们会多次重新分配工作

由于此问题在使用基于numpy的数据结构的科学计算中经常出现,joblib.Parallel为大型阵列提供了一种特殊的处理方法,用于自动将它们转储到文件系统中,并将引用传递给工作者,以便使用numpy.ndarray的numpy.memmap子类将它们作为该文件上的内存映射打开。这使得在所有工作进程之间共享一段数据成为可能

注意:以下仅适用于默认的“多处理”后端。如果您的代码可以释放GIL,那么使用backend=“threading”更有效

因此,如果这是您的情况,您应该切换到线程后端,如果您能够在调用
frame
时释放全局解释器锁,或者切换到
joblib
的共享内存方法


假设
joblib
提供了一个自动化的
memmap
转换,这可能非常有用。

很可能您遇到的问题是python编译器本质上的一个基本问题

如果您阅读“”,您可以从一位专门研究优化和并行化python代码的专业人士那里看到,对于python线程来说,迭代大型循环本身就是一种缓慢的操作。因此,产生更多在阵列中循环的进程只会降低速度

然而,有些事情是可以做到的

和编译器的设计都是为了优化类似于C/C++风格(即您的案例)的代码-特别是Numba的新装饰器允许标量函数以并行方式在具有大型数组的大型数组上接受和应用操作(
target=parallel


我对您的代码理解不够,无法给出一个实现示例,但请尝试一下!这些以正确方式使用的编译器在过去为我带来了300万%的并行进程速度提升

首先,您运行此应用程序的计算机中有多少CPU或内核?其次,
n_作业
设置并发运行作业的最大数量。您是否尝试过
n\u jobs=-1
?这应该使用计算机中的所有CPU。第三,这个for循环的
索引有多大?我有24个内核和大量内存。Indees大约有10000个条目,所以我认为这将是一个并行化的好事情。我可以试试n_jobs=-1,然后回来报到。是的。我可以想象,如果你将n_jobs从1增加到最大值(n_jobs=23,njobs=-1),那么你将达到一个点,增加这个数字将涉及更多的开销,因此你必须找到一个最佳点。当然,如果你能使用backend=“threading”可能会更好,但你必须进行实验。然后,我想推荐这篇SO文章,它有非常好的答案,其中一篇直接来自joblib作者,尽管可能已经过时了。。。