mpi send / recv массивы переменной длины в структуре - PullRequest
0 голосов
/ 19 октября 2018

Мне нужно иметь возможность отправлять и получать два массива uint64_t для всех рангов с ранга 0.

У меня есть структура typedef следующим образом:

typedef struct _mpi_data_t {
    uint64_t *array1;
    uint64_t *array2;
    size_t array1_size;
    size_t array2_size;
} mpi_data_t;

В ранге 0 язаполните массивы и вычислите смещения, чтобы создать тип данных mpi.

MPI_Get_address(&mpi_data_send, &address[0]);
MPI_Get_address(&mpi_data_send.array1[0], &address[1]);
MPI_Get_address(&mpi_data_send.array2[0], &address[2]);
MPI_Get_address(&mpi_data_send.array1_size, &address[3]);
displacements[0] = address[1] - address[0];
displacements[1] = address[2] - address[0];
displacements[2] = address[3] - address[0]; 

Я также установил массив счетчиков блоков следующим образом:

int block_count[3] = {mpi_data_send.array1_size, mpi_data_send.array2_size, 2};

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

Как я могу отправить и получить эти два динамически изменяемых массива?

1 Ответ

0 голосов
/ 20 октября 2018

Вы можете использовать MPI_Probe и MPI_Get_count для определения длины принимаемого сообщения.
Вы не предоставляете формат отправки и получения в своем коде, но в качестве предложения вы можете отправлять массив отдельно и получать их.Этот пример C может помочь:

// Author: Wes Kendall
// Copyright 2011 www.mpitutorial.com
// This code is provided freely with the tutorials on mpitutorial.com. Feel
// free to modify it for your own use. Any distribution of the code must
// either provide a link to www.mpitutorial.com or keep this header intact.
//
// Example of using MPI_Probe to dynamically allocated received messages
//
#include <mpi.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main(int argc, char** argv) {
  MPI_Init(NULL, NULL);

  int world_size;
  MPI_Comm_size(MPI_COMM_WORLD, &world_size);
  if (world_size != 2) {
    fprintf(stderr, "Must use two processes for this example\n");
    MPI_Abort(MPI_COMM_WORLD, 1);
  }
  int world_rank;
  MPI_Comm_rank(MPI_COMM_WORLD, &world_rank);

  int number_amount;
  if (world_rank == 0) {
    const int MAX_NUMBERS = 100;
    int numbers[MAX_NUMBERS];
    // Pick a random amont of integers to send to process one
    srand(time(NULL)+world_rank);
    number_amount = (rand() / (float)RAND_MAX) * MAX_NUMBERS;
    // Send the amount of integers to process one
    MPI_Send(numbers, number_amount, MPI_INT, 1, 0, MPI_COMM_WORLD);
    printf("0 sent %d numbers to 1\n", number_amount);
  } else if (world_rank == 1) {
    MPI_Status status;
    // Probe for an incoming message from process zero
    MPI_Probe(0, 0, MPI_COMM_WORLD, &status);
    // When probe returns, the status object has the size and other
    // attributes of the incoming message. Get the size of the message.
    MPI_Get_count(&status, MPI_INT, &number_amount);
    // Allocate a buffer just big enough to hold the incoming numbers
    int* number_buf = (int*)malloc(sizeof(int) * number_amount);
    // Now receive the message with the allocated buffer
    MPI_Recv(number_buf, number_amount, MPI_INT, 0, 0, MPI_COMM_WORLD,
         MPI_STATUS_IGNORE);
    printf("1 dynamically received %d numbers from 0.\n",
       number_amount);
    free(number_buf);
  }
  MPI_Finalize();
}

, в этом примере массив произвольной длины (менее 100), выделенный в ранге 0 и отправленный в ранг 1.

...