Python: как преобразовать цикл for в функции, которая зависит от больших массивов, в параллельный цикл for - PullRequest
0 голосов
/ 05 сентября 2018

Я пытаюсь использовать multiprocess в Python 3 для преобразования цикла for в параллельный цикл for в Windows.Подвох заключается в том, что обрабатываемые массивы должны иметь общую память, потому что в противном случае у меня закончится память.Как я могу распараллелить код внизу этого сообщения?

Вызов bigExampleArray = multiprocessing.Array(bigExampleArray) должен преобразовать его в массив с общей памятью для многопроцессорной обработки, насколько я понял.И я рассмотрел несколько примеров, которые все полагаются на создание определений функций для параллельной работы, но я не уверен, как передать все, что мне нужно, в функцию, когда я вызываю ее, используя один из множества * 1006.* методы.Например:

p = multiprocessing.Process(target=parallelForLoopFun, args=(bigExampleArray, bigChangingArray));
p.start();

или

p = multiprocessing.Pool(4);
p.map(parallelForLoopFun, someConstantArray?);

Я не вижу способа отправить то, что я хочу, с помощью iCntr, с вышеуказанными способами вызова параллельных рабочих функций - или свызов карты, как легко отправлять несколько многомерных массивов.

Я пробовал пакет numba с @jit (примененным до определения в функции) и range -> prange, но этоне смог ускорить мой более сложный код.(Используйте from numba import jit, prange, чтобы импортировать его, если вы еще не пробовали numba)

В идеале я хотел бы иметь возможность преобразовать цикл for в параллель цикла for с помощью простого вызова range ->prange - но если требуется отдельная функция, в идеале это должно быть что-то вроде:

def parallelForLoopFun(iCntr,bigExampleArray,bigChangingArray)
    if( bigExampleArray[iCntr,2] > 0.5 ):
        temporaryNumber = np.int32(11+iCntr);
    else:
        temporaryNumber = np.int32(1+iCntr);
    bigChangingArray[iCntr,:] = np.array( [bigExampleArray[iCntr,1],bigExampleArray[iCntr,2]+temporaryNumber] );

Для подготовки примеров массивов этот код должен работать:

import numpy as np
import time
from test_fun import tediusConverter #I named the function file test_fun

bigExampleArray = np.random.rand(100000000,3);
tic = time.time(); #for time testing
bigReturnedArray = tediusConverter(bigExampleArray);
toc = time.time() - tic; #for time testing
print("\nTime to run: {} sec\n".format(toc)); #extra space at end

Ниже приведенофункция, которую я хотел бы распараллелить:

import numpy as np

def tediusConverter(bigExampleArray):
    bigChangingArray = np.zeros( (len(bigExampleArray[:,0]) , 2 ) ); #preallocate 

    for iCntr in range(0, len(bigExampleArray[:,0])):
        if( bigExampleArray[iCntr,2] > 0.5 ):
            temporaryNumber = np.int32(11+iCntr);
        else:
            temporaryNumber = np.int32(1+iCntr);
        bigChangingArray[iCntr,:] = np.array( [bigExampleArray[iCntr,1],bigExampleArray[iCntr,2]+temporaryNumber] );
    return bigChangingArray;

Приведенный выше код является обобщением, чтобы облегчить (надеюсь) понимание и применение к другим вещам.На моем 4C i5-4960k с частотой 4,5 ГГц вышеупомянутый процесс занимает ~ 205 секунд.Наконец, обратите внимание, что numba @jit(nopython=False,parallel=True) и range -> prange могут работать с этим упрощенным кодом и видеть время выполнения ~ 12 секунд и использовать ~ 100% ЦП - так что естьнадеюсь!(nopython=True также работает при времени выполнения ~ 8 секунд ...)

...