Используйте MPI_Scatterv для рассеяния перекрывающихся областей массива

У меня есть представление 1D-массива 2D-массива: ниже приведен пример 6x6:

[00000012300456700890100234500000] => [------]
                                      [|0123|]
                                      [|4567|]
                                      [|8901|]
                                      [|2345|]
                                      [------]

Типичный размер будет 514 * 514 элементов (512 + 2 ячейки гало). Я должен распределить данные между, скажем, четырьмя процессорами:

Rank 0:        Rank 1:      Rank 2:        Rank 3:      
  [----]          [----]      [|456]          [567|]
  [|012]          [123|]      [|890]          [901|]
  [|456]          [567|]      [|234]          [345|]
  [|890]          [901|]      [----]          [----]

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

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

Как я могу распространять данные с таким перекрытием?

=== РЕДАКТИРОВАТЬ ===

После использования вашей реализации этого Джонатон ...

Я пытаюсь сделать это в настоящее время с массивом символов (2D), но я получаю «мусор» при сборе их из процессоров / рангов. Я изменил тип и все, но не могу понять, где проблема в данный момент.

void distributeBySend_c(unsigned char **global, const int globalrows, const int globalcols,
                  const int localrows, const int localcols,
                  const int rank, const int size,
                  MPI_Comm cartcomm, const int dims[2], const int coords[2]) {

MPI_Request reqs[dims[0]*dims[1]];
const int tag = 1;

if (rank == 0) {
    MPI_Datatype block;
    int starts[2] = {0,0};
    int subsizes[2] = {localrows, localcols};
    int sizes[2] = {globalrows, globalcols};
    MPI_Type_create_subarray(2, sizes, subsizes, starts, MPI_ORDER_C, MPI_CHAR, &block);
    MPI_Type_commit(&block);

    int reqno=0;
    for (int i=0; i<dims[0]; i++) {
        int startrow = i*datasize;
        int destcoords[2];
        destcoords[0] = i;
        for (int j=0; j<dims[1]; j++) {
            int startcol = j*datasize;
            destcoords[1] = j;                

            int dest;
            MPI_Cart_rank(cartcomm, destcoords, &dest);
            MPI_Isend(&(global[startrow][startcol]), 1, block, dest, tag, cartcomm, &reqs[reqno++]);
        }
    }
}

unsigned char **local = alloc2dImage(localrows, localcols);
MPI_Recv(&(local[0][0]), localrows*localcols, MPI_CHAR, 0, tag, cartcomm, MPI_STATUS_IGNORE);

if (rank == 0)
    MPI_Waitall(dims[0]*dims[1], reqs, MPI_STATUS_IGNORE);

eachprintarr_c(local, localrows, localcols, rank, size);
}

Результат, который я получаю:

---
Rank   0: ? ? ? ? 
Rank   0: � ' V � 
Rank   0: � ' V � 
Rank   0: � ' V � 
---
Rank   1: ? ? ? ? 
Rank   1: � � � % 
Rank   1: � � � % 
Rank   1: � � � % 
---
Rank   2: ? + + + 
Rank   2: � � � � 
Rank   2: � � � � 
Rank   2: � � � � 
---
Rank   3: + + + ? 
Rank   3: �  � � 
Rank   3: �  � � 
Rank   3: �  � � 

Ответы на вопрос(1)

Ваш ответ на вопрос