многопроцессорность замедляет мой код, а не ускоряет его - PullRequest
0 голосов
/ 02 марта 2019

Я успешно использовал multiprocessing.dummy.Pool во многих кодах, чтобы ускорить время вычисления циклов.Однако я столкнулся с проблемой, которую не могу понять: куда больше потоков я добавляю, тем медленнее работает код.Это все в Python 2.7, работающем на 8-ядерном windoze box.

import numpy as np
from multiprocessing.dummy import Pool 
from datetime import datetime
global X

pool=Pool(processes=1)

def foo(iy):
    global X
    x=X[iy]
    for i in range(len(x)):
        for j in range(len(x[i])):
            _=np.correlate(x[i,j],[1,1,1],mode='same')
    return None

t=datetime.now()
X=np.random.rand(11,11,512,512)
_=pool.map(foo,range(11))
print((datetime.now()-t).total_seconds())

с processes=1, это выполняется за 0,7 с.Увеличивается до 1 сек с processes=2 и 2,3 сек если processes=4.Та же проблема возникает, если я переписываю код следующим образом:

import numpy as np
from multiprocessing.dummy import Pool 
from datetime import datetime

pool=Pool(processes=1)

def foo(x):
    for i in range(len(x)):
        for j in range(len(x[i])):
            _=np.correlate(x[i,j],[1,1,1],mode='same')
    return None

t=datetime.now()
X=np.random.rand(11,11,512,512)
_=pool.map(lambda z:foo(X[z]),range(11))
print((datetime.now()-t).total_seconds())

У меня есть много циклов, и я действительно хочу / нуждаюсь в ускорении от разделения их на несколько ядер.У кого-нибудь есть мысли о том, почему многопроцессорность замедляет меня и как это исправить?

1 Ответ

0 голосов
/ 02 марта 2019

Хотя np.correlate() может (и, возможно, в вашем случае) высвобождает GIL , я думаю, что ваши данные слишком малы, чтобы принести какую-либо выгоду.То есть ваш код Python (циклы) конкурирует за GIL, наряду с частями «пролог» и «эпилог» np.correlate() (которые содержат GIL).

У вас есть несколько вариантовчтобы улучшить ваш параллелизм:

  1. Реализуйте все ваши вычисления, используя numba.jit(nogil=True).Но там доступно только подмножество NumPy, и я не думаю, что оно включает np.correlate().
  2. Реализуйте свои вычисления, используя какой-то другой язык, такой как Cython или C, и освободите GIL во время вычислений.
  3. Переключение с multiprocessing.dummy (в котором используются потоки) на multiprocessing (в котором используются процессы, поэтому нет конкуренции за GIL).
  4. Используйте большие данные в каждом вызове np.correlate().
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...