问:(为什么)...运行速度比正常的 for 循环慢(?)
>>> 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]
(50,50,50)
鉴于-of-的微型数据形状float64
,缓存内计算是性能的关键。使用joblib.Parallel
带有 ' threading
' 后端的 a 是相当反模式的(python 使用GIL
-lock 以便一步一步[SERIAL]
地重新计算计算,因为它避免了任何常见的、与并发相关的冲突)。这样的串行计算流程在这里更糟糕,因为“切换”一个接一个地需要额外的成本(没有改善原始的纯代码执行——所以你需要付出更多才能获得相同的结果(然而,在更长的时间))[SERIAL]
Q :增加n_jobs
也会增加处理时间
当然,它增加了 GIL 锁重新[SERIAL]
化开销所浪费的时间量,因为有更多one-step-after-another
GIL 导向的冲突避免“切换”转换。
最后但并非最不重要的
即使进入完全成熟的并行性,使用基于进程的并行性(避免 GIL 锁定的成本),它也会出现(再次以成本 - 进程实例化成本(python 的完整 1:1 内存副本)n_jobs
Win O/S 中的解释器进程时间,类似地在 linux O/S 中 - 如joblib
模块中所述,包括避免一些其他形式的产生并行进程的建议)、参数 data-transfer-cost、result-transfer-cost )。
如果将所有这些附加成本添加到n_jobs = 6
,并且如果这些成本只是以微型计算任务的名义产生的(小~ 680 [ms]
到持续时间),那么很快就会导致为设置并行处理支付更多费用比以往任何时候都收到回(因为其他效果 - 作为比原始缓存重用更差 - 不会“提高”计算速度)。
计算有效载荷的实际成本(以及对每一类(所有此类)成本的适当考虑)是原因 (为什么)......运行速度较慢