Python joblib.Parallel()对于skimage比single慢

Python joblib.Parallel()对于skimage比single慢,python,parallel-processing,cpu,joblib,parallelism-amdahl,Python,Parallel Processing,Cpu,Joblib,Parallelism Amdahl,我必须对一堆图像的每一个切片应用2D过滤器,并且我想并行化分析。但是,下面的代码比正常的for循环运行得慢。另外,增加n_作业也会增加处理时间,对于n_作业=1而言,处理时间更快,对于n_作业=6而言,处理时间更慢 import numpy as np from joblib import Parallel, delayed from skimage.restoration import denoise_tv_chambolle arr = np.random.rand(50,50,50)

我必须对一堆图像的每一个切片应用2D过滤器,并且我想并行化分析。但是,下面的代码比正常的for循环运行得慢。另外,增加
n_作业
也会增加处理时间,对于
n_作业=1
而言,处理时间更快,对于
n_作业=6
而言,处理时间更慢

import numpy as np 
from joblib import Parallel, delayed
from skimage.restoration import denoise_tv_chambolle

arr = np.random.rand(50,50,50)

def f(arr):
    arr_h = denoise_tv_chambolle(arr, weight=0.1, multichannel=True)
    return arr_h

Parallel(n_jobs=6, backend="threading")(delayed(f)(i) for i in arr)
Q:(为什么)运行速度比正常for循环(?)慢

考虑到-
float64
的微型数据形状
(50,50,50)
,缓存内计算是性能的关键。使用带有“
线程化”后端的
joblib.Parallel
是一种反模式(python使用
GIL-lock,以便一步一步地重新执行
[SERIAL]
-ise计算,因为它避免了任何常见的、与并发相关的冲突)。这种串行计算流在这里更糟糕,因为一步一步地“切换”会带来额外的成本(而不是改进原始的纯-
[serial]
代码执行-因此您需要支付更多的费用才能获得相同的结果(但是,在更长的时间之后))

Q:增加
n\u作业
也会增加处理时间

当然,这会增加GIL锁重设(
[SERIAL]
-isation)开销的浪费时间,因为一步接一步地有更多的GIL定向碰撞避免(切换()转换


最后不能不提 即使使用基于流程的并行(避免GIL锁定的成本)进入成熟的并行,它也会出现(同样是以流程实例化成本为代价的)(python解释器进程的完整1:1内存拷贝
n_jobs
-在Win O/S中运行了多次,在linux O/S中也一样-如
joblib
模块中所述,包括避免生成并行进程的其他形式的建议)、参数数据传输成本、结果传输成本)

如果将所有这些附加成本加在
n_jobs=6
上,并且如果这些成本只是以小型计算任务的名义累积的(持续时间小到
~680[ms]
),很快就会导致设置并行处理所需的费用远远高于将收到的(因为其他影响——比原始缓存重复使用更糟糕——不会“提高”计算速度)

这是原因(为什么)
运行较慢

Q:(为什么).运行速度比正常的for循环(?)慢

考虑到-
float64
的微型数据形状
(50,50,50)
,缓存内计算是性能的关键。使用带有'
线程化'
'后端的
joblib.Parallel
是相当反模式的(python使用
GIL
-锁以重新执行
[串行]
-一步一步地对计算进行ise,因为它避免了任何常见的、与并发相关的冲突)。这种串行计算流在这里更糟糕,因为一步一步地“切换”需要额外的成本(而不是改进原始的纯-
[串行]
代码执行-因此您需要支付更多的费用才能收到相同的代码(但是,经过更长的时间)

Q:增加
n\u作业
也会增加处理时间

当然,这会增加GIL锁重设(
[SERIAL]
-isation)开销的浪费时间,因为一步接一步地有更多的GIL定向碰撞避免(切换()转换


最后不能不提 即使使用基于流程的并行(避免GIL锁定的成本)进入成熟的并行,它也会出现(同样是以流程实例化成本为代价的)(python解释器进程的完整1:1内存拷贝
n_jobs
-在Win O/S中运行了多次,在linux O/S中也一样-如
joblib
模块中所述,包括避免生成并行进程的其他形式的建议)、参数数据传输成本、结果传输成本)

如果将所有这些附加成本加在
n_jobs=6
上,并且如果这些成本只是以小型计算任务的名义累积的(持续时间小到
~680[ms]
),很快就会导致设置并行处理所需的费用远远高于将收到的(因为其他影响——比原始缓存重复使用更糟糕——不会“提高”计算速度)


这就是原因。运行速度较慢

那么,没有办法让进程更快吗?我现在正在尝试np.memmap,但它仍然很慢。
np.memmap()
-s是
~10[ms]
每次随机访问,可以在
~0.5[ns]中智能重用缓存数据
…所以你试图用
np.memmap()
-sSo让事情变得更糟很多个数量级,难道没有办法让这个过程更快吗?我现在正在尝试np.memmap,但它仍然很慢。
np.memmap()
-s是
~10[ms]
每次随机访问,可以在
~0.5[ns]中智能重用缓存数据
…因此,您尝试使用
np.memmap()
-s使事情变得更糟
>>> import numpy as np; _ = np.random.rand( 50, 50, 50)
>>> from zmq import Stopwatch; aClk = Stopwatch()
>>> 
>>> aClk.start(); r = denoise_tv_chambolle( _, weight = 0.1, multichannel = True ); b = aClk.stop(); print( "The code took {0: > 9d}[us]".format( b ) )
The code took    679749[us]
The code took    683137[us]
The code took    678925[us]
The code took    688936[us]