MPI Scatterv для вспомогательного коммуникатора (с использованием COMM_WORLD.Split()) не работает должным образом

Я запускаю скрипт ниже, используя mpirun -n 40 python script.py. Цель состоит в том, чтобы распараллелить функцию func. Здесь происходит то, что пул из 40 «рабочих» разделен на 5 блоков по 8 «рабочих» (каждый блок имеет свой цвет, конечно). Я генерирую аргументы (gen_args) для каждого блока и объединяю их в массив 1D numpy. Затем я использую ScatterV, чтобы разбросать этот сглаженный массив по «рабочим» в одном блоке. Разбросанное значение фиксируется в переменной recv_args.

Все работает хорошо (исходя из выводов на печать, которые я видел), за исключением block_comm.Scatterv([send_data,counts,displacement, MPI.DOUBLE], recv_args, root=0) Каким-то образом он устанавливает все элементы массива recv_args (во всех рангах) равными нулю (имейте в виду, что изначально они являются единицами во всех рангах) Что такое Я пропал здесь?

Вот MCVE:

import numpy as np
from mpi4py import MPI

def func(arg1, arg2,arg3):
  return arg1+arg2+arg3

def gen_args(const, n_iter):     #More complicated ofcourse in reality
  return const*np.arange(n_iter*3).reshape((n_iter,3))

if __name__ == '__main__':
    world_comm = MPI.COMM_WORLD
    world_size = world_comm.Get_size()    #  normally 40
    world_rank = world_comm.Get_rank()

    block_size = 8
    blocks = int(world_size/block_size)

    color = int(world_rank/block_size)
    key = int(world_rank%block_size)

    block_comm = world_comm.Split(color,key)
    #Effectively world_comm (size=40) is now split in 5 blocks of size=8

    block_rank = block_comm.Get_rank()
    print("WORLD RANK/SIZE: {}/{} \t BLOCK RANK/SIZE: {}/{}".format(world_rank, world_size, block_rank, block_size))

    recv_args= np.ones(3)
    counts = tuple(np.ones(block_size)*3)
    displacement = tuple(np.arange(block_size)*3)

    if block_rank==0:
      send_data = gen_args(color, block_size).flatten()
      print(send_data)
    else:
      send_data = None

    block_comm.Scatterv([send_data,counts,displacement, MPI.DOUBLE], recv_args, root=0)
    print(block_rank,recv_args)

person krishan    schedule 13.06.2018    source источник
comment
color=0 в первых 8 задачах, поэтому recv_args здесь должно быть равно нулю. Что, если вы block_size=2 запустите 4 задачи? Можете ли вы загрузить вывод? Обратите внимание, что это не минимально воспроизводимый пример, строго говоря, поскольку вы не проверяете вывод (например, recv_args). Какая библиотека MPI mpi4py построена поверх ?   -  person Gilles Gouaillardet    schedule 13.06.2018
comment
@GillesGouaillardet, ты прав, ответ по этой ссылке мне помог. Я думал, что делаю что-то не так с разделением, но проблема была с автоматическими типами данных моих пустых массивов. Мне всегда приходится заставлять их использовать numpy.float64.   -  person krishan    schedule 13.06.2018


Ответы (1)


Проблема заключается в типах данных send_data и recv_args (как видно и здесь: Как разбросать массив numpy в python с помощью comm.Scatterv ). Они должны иметь тип данных np.float64, когда я объявляю тип данных как MPI.DOUBLE для Scatterv.

Были внесены следующие изменения:

def gen_args(const, n_iter):  
  return const*np.arange(n_iter*3,dtype=np.float64).reshape((n_iter,3))

а также

recv_args= np.ones(3,dtype=np.float64)
person krishan    schedule 13.06.2018