2015-03-20 3 views
1

У меня есть скрипт python, который набирает MPI для параллельных вычислений. Схема расчетов следующая: обработка данных раунд 1 - обмен данными между процессами - обработка данных раунд 2. У меня есть 16 логических ядерных машин (2 x Intel Xeon E5520 2,27 ГГц). По этой причине раунд 1 не может быть запущен параллельно. Таким образом, 15 ядер остаются без дела. Однако, несмотря на этот факт, расчеты испытывают более чем двукратное замедление.mpi4py: существенное замедление по незанятым ядрам

Проблемы иллюстрируется этот сценарий (сохраняются как test.py):

from mpi4py import MPI 
import time 

comm = MPI.COMM_WORLD 
rank = comm.Get_rank() 
size = comm.Get_size() 
comm.barrier() 
stime = time.time() 

if rank == 0: 
    print('begin calculations at {:.3f}'.format(time.time() - stime)) 
    for i in range(1000000000): 
     a = 2 * 2 
    print('end calculations at {:.3f}'.format(time.time() - stime)) 
    comm.bcast(a, root = 0) 
    print('end data exchange at {:.3f}'.format(time.time() - stime)) 
else: 
    a = comm.bcast(root = 0) 

Когда я запустить его на 2 ядра, наблюдает:

$ mpiexec -n 2 python3 test.py 
begin calculations at 0.000 
end calculations at 86.954 
end data exchange at 86.954 

Когда я запустить его на 16 ядер, Я наблюдаю:

$ mpiexec -n 16 python3 test.py 
begin calculations at 0.000 
end calculations at 174.156 
end data exchange at 174.157 

Может ли кто-нибудь объяснить такую ​​разницу? Идея, как избавиться от нее, также была бы полезна.

ответ

0

ОК, я, наконец, понял это.

Есть несколько особенностей, способствующих замедлению:

  • Ожидание приема данных является активным (он проверяет постоянно, если данные уже прибыли), что делает процессы, ожидающие не более простаивает.
  • Виртуальные ядра Intel не способствуют скорости вычислений. Это означает, что 8-ядерная машина по-прежнему имеет 8 ячеек и ведет себя как таковая, независимо от виртуальных (в некоторых случаях, например, когда применяется модуль multithreading, они могут сделать скромный импульс, но не с MPI).

Учитывая это, я модифицировал код, вводя функцию sleep() в процессы ожидания. Результаты представлены на графике (в каждом случае было выполнено 10 измерений).

from mpi4py import MPI 
import time 

comm = MPI.COMM_WORLD 
rank = comm.Get_rank() 
size = comm.Get_size() 
comm.barrier() 
stime = time.time() 

if rank == 0: 
    for i in range(1000000000): 
     a = 2 * 2 
    print('end calculations at {:.3f}'.format(time.time() - stime)) 
    for i in range(1, size): 
     comm.send(a, dest = i) 
    print('end data exchange at {:.3f}'.format(time.time() - stime)) 
else: 
    while not comm.Iprobe(source = 0): 
     time.sleep(1) 
    a = comm.recv(source = 0) 

enter image description here

Смежные вопросы