11.2. 如何并行化循环#

在图像处理中,我们经常对大量图像应用相同的算法。在本段中,我们建议使用 joblib 来并行化循环。以下是一个此类重复性任务的示例

import skimage as ski

def task(image):
    """
    Apply some functions and return an image.
    """
    image = ski.restoration.denoise_tv_chambolle(
        image[0][0], weight=0.1, channel_axis=-1
    )
    fd, hog_image = ski.feature.hog(
        ski.color.rgb2gray(image),
        orientations=8,
        pixels_per_cell=(16, 16),
        cells_per_block=(1, 1),
        visualize=True
    )
    return hog_image


# Prepare images
hubble = ski.data.hubble_deep_field()
width = 10
pics = ski.util.view_as_windows(
    hubble, (width, hubble.shape[1], hubble.shape[2]), step=width
)

要对列表 pics 中的每个元素调用函数 task,通常会编写一个 for 循环。要测量此循环的执行时间,可以使用 ipython 并使用 %timeit 测量执行时间。

def classic_loop():
    for image in pics:
        task(image)


%timeit classic_loop()

另一种等效的编码此循环的方法是使用具有相同效率的列表推导式。

def comprehension_loop():
    [task(image) for image in pics]

%timeit comprehension_loop()

joblib 是一个库,它提供了一种简单的方法来并行化 for 循环,前提是我们有一个列表推导式。可以指定作业数量。

from joblib import Parallel, delayed
def joblib_loop():
    Parallel(n_jobs=4)(delayed(task)(i) for i in pics)

%timeit joblib_loop()