2016-04-15 1 views
1

Это моя первая программа MPI на языке python, и я очень благодарен за помощь в оптимизации кода. В частности, у меня есть два вопроса относительно рассеяния и сбора, если кто-то может помочь. Эта программа намного медленнее, чем традиционный подход без MPI.Распределение параметров для коллективов MPI

Я пытаюсь разбить один массив, выполнить некоторую работу над узлами, которые заполняют другой набор массивов, и собрать их. Мои вопросы в первую очередь касаются установки и сбора разделов кода.

  • Нужно ли выделять память для массива на всех узлах? (A, my_A, xset, yset, my_xset, my_yset)? Некоторые из них могут стать большими.
  • Является ли массив лучшей структурой для сбора данных, которые я использую? Когда я разбрасываю А, он относительно мал. Однако xset и yset могут получить очень большие (по крайней мере, более миллиона элементов).

Вот код:

#!usr/bin/env python 

#Libraries 
import numpy as py 
import matplotlib.pyplot as plt 
from mpi4py import MPI 

comm = MPI.COMM_WORLD 
print "%d nodes running."% (comm.size) 

#Variables 
cmin = 0.0 
cmax = 4.0 
cstep = 0.005 
run = 300 
disc = 100 

#Setup 
if comm.rank == 0: 
    A = py.arange(cmin, cmax + cstep, cstep) 
else: 
    A = py.arange((cmax - cmin)/cstep, dtype=py.float64) 

my_A = py.empty(len(A)/comm.size, dtype=py.float64) 
xset = py.empty(len(A) * (run - disc) * comm.size, dtype=py.float64) 
yset = py.empty(len(A) * (run - disc) * comm.size, dtype=py.float64) 
my_xset = py.empty(0, dtype=py.float64) 
my_yset = py.empty(0, dtype=py.float64) 

#Scatter 
comm.Scatter([A, MPI.DOUBLE], [my_A, MPI.DOUBLE]) 

#Work 
for i in my_A: 
    x = 0.5 
    for j in range(0, run): 
     x = i * x * (1 - x) 
     if j >= disc: 
      my_xset = py.append(my_xset, i) 
      my_yset = py.append(my_yset, x) 

#Gather 
comm.Allgather([my_xset, MPI.DOUBLE], [xset, MPI.DOUBLE]) 
comm.Allgather([my_yset, MPI.DOUBLE], [yset, MPI.DOUBLE]) 

#Export Results 
if comm.rank == 0: 
    f = open('points.3d', 'w+') 
    for k in range(0, len(xset)-1): 
     f.write('(' + str(round(xset[k],2)) + ',' + str(round(yset[k],2)) + ',0)\n') 
    f.close() 

ответ

0
  • Вам не нужно выделять A на некорневых процессы. Если вы не использовали Allgather, но просто Gather, вы также можете опустить xset и yset. В основном вам нужно всего лишь выделить данные, которые фактически используются коллективами, - другие параметры: , только значимые для корня.

  • Да, массив numpy является подходящей структурой данных для таких больших массивов. Для небольших данных, где он не критичен по производительности, может быть более удобным и pythonic использовать все строчные методы и общаться с объектами Python (списки и т. Д.).