Распараллеливание Python цикл - PullRequest
1 голос
/ 27 мая 2020

Я немного заблудился между joblib, multiprocessing и т.д. c ..

Какой самый эффективный способ распараллелить для l oop, на основе вашего опыта?

Например:

for i, p in enumerate(patches[ss_idx]):
            bar.update(i+1)
            h_features.append(calc_haralick(p)) 
def calc_haralick(roi):

    feature_vec = []

    texture_features = mt.features.haralick(roi)
    mean_ht = texture_features.mean(axis=0)

    [feature_vec.append(i) for i in mean_ht[0:9]]

    return np.array(feature_vec)

Он получает i фрагментов изображений, а затем извлекает функции через haralick

И вот так получаются патчи

 h_neigh = 11 # haralick neighbourhood
 size = h_neigh
 shape = (img.shape[0] - size + 1, img.shape[1] - size + 1, size, size)
 strides = 2 * img.strides
 patches = stride_tricks.as_strided(img, shape=shape, strides=strides)
 patches = patches.reshape(-1, size, size)

Извините, если какая-то информация лишняя

1 Ответ

1 голос
/ 27 мая 2020

Ваши изображения выглядят как простые двумерные NumPy массивы и patches их список или массив. Я предполагаю, что ss_idx является индексным массивом (т. Е. Не целым числом), поэтому patches[ss_idx] остается чем-то, что можно повторять (как в вашем примере).

В этом случае просто используйте multiprocessing.Pool.map:

import multiprocessing as mp

nproc = 10
with mp.Pool(nproc) as pool:
    h_features = pool.map(calc_haralick, patches[ss_idx])

См. Первый пример basi c в документации multiprocessing .

Если вы оставите nproc или установите его на None , будут использованы все доступные ядра.


Потенциальная проблема с многопроцессорностью заключается в том, что она создаст nproc идентичных Python процессов и скопирует все соответствующие данные в эти процессы. Если ваши изображения большие, это вызовет значительные накладные расходы.

В таком случае, возможно, стоит разделить вашу Python программу на отдельные программы, где вычисление будущего одного изображения является одной независимой программой. . Эта программа должна обрабатывать чтение одного изображения и запись функций. Затем вы оберните все, например, в сценарий bash, который перебирает все изображения, заботясь об использовании только определенного количества ядер одновременно (например, фоновые процессы, но wait каждые 10 изображений). Следующий шаг / программа требует чтения независимых файлов функций в многомерный массив, но оттуда вы можете продолжить свою старую программу.

Хотя это больше работы, это может сэкономить некоторые накладные расходы на копирование (хотя это вводит дополнительные накладные расходы ввода-вывода, в частности, написание отдельных файлов функций).
Он также имеет дополнительное преимущество, состоящее в том, что это довольно легко запустить распределенно, если такая возможность когда-либо возникнет.


Попробуйте многопроцессорность, отслеживание использования памяти и использования ЦП (если ничего не происходит в течение длительного времени, это может быть накладные расходы на копирование). Затем попробуйте другой метод.

...