Простой MPI-код для тестирования сбоя MPI_Type_vector с ошибкой seg — почему?

#c #mpi #parallel-processing #hpc

#c #mpi #параллельная обработка #hpc

Вопрос:

У меня есть следующий код, который я использую, чтобы проверить, как я использую MPI_Type_vector в другой программе. Я написал эту небольшую тестовую программу, чтобы я мог проверить параметры, которые я предоставляю MPI_Type_vector, чтобы убедиться, что они извлекают правильные части массива. Однако, похоже, он не работает должным образом — при запуске он выдает ошибки сегментации (даже если сначала выполняет часть выходных данных), и я, похоже, не могу понять, почему.

Есть идеи?

Код приведен ниже. Первая функция ( alloc_3d_int ) была предоставлена мне кем-то другим, но была хорошо протестирована.

 #include <stdio.h>
#include <stdlib.h>
#include <time.h>

#include "array_alloc.h"
#include <mpi.h>


/* 3D array allocation program given to me by someone else */
int   ***alloc_3d_int  ( int ndim1, int ndim2, int ndim3 ) {

  int   *space = malloc( ndim1 * ndim2 * ndim3 * sizeof( int  ) );

  int  ***array3 = malloc( ndim1 * sizeof( int  ** ) );

  int i, j;

  if( space == NULL || array3 == NULL )
    return NULL;

  for( j = 0; j < ndim1; j   ) {
    array3[ j ] = malloc( ndim2 * sizeof( int * ) );
    if( array3[ j ] == NULL )
      return NULL;
    for( i = 0; i < ndim2; i   ) 
      array3[ j ][ i ] = space   j * ( ndim3 * ndim2 )   i * ndim3;
  }

  return array3;

}

void print_data(int *start, int count, int blocklen, int stride)
{
    int i, j;
    int *curr;
    int *new;

    MPI_Datatype new_type;

    /* Create an array to store the output in - just a 1D array */
    new = alloc_1d_int(count*blocklen);

    /* Create the vector type using the parameters given to the function (came from the cmd line args) */
    MPI_Type_vector(count, blocklen, stride, MPI_INT, amp;new_type);
    MPI_Type_commit(amp;new_type);

    /* Do the send and receive to this process */
    MPI_Sendrecv(amp;start, 1, new_type, 0, 0, amp;new, count*blocklen, MPI_INT, 0, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);

    /* Loop through the array it was received into, printing values */
    for (i = 0; i < count*blocklen; i  )
    {
        printf("%dn", new[i]);
    }
    printf("Done loop");
}

int main(int argc, char ** argv)
{
    int ***data;
    int i, j, k;
    int num;
    int a, b, c;

    MPI_Init(amp;argc, amp;argv);

    /* Create a 3D array */
    data = alloc_3d_int(2, 3, 4);

    num = 1;

    /* Fill array with test values */
    for (i = 0; i < 2; i  )
    {
        for (j = 0; j < 3; j  )
        {
            for (k = 0; k < 4; k  )
            {
                data[i][j][k] = num;
                num  ;
            }
        }
    }

    /* Get values from cmd line arguments */
    a = atoi(argv[1]);
    b = atoi(argv[2]);
    c = atoi(argv[3]);

    printf("Using count = %d, blocklength = %d and stride = %dn", a, b, c);

    /* Do the communication and print results */
    print_data(amp;data[0][0][0], a, b, c);

    MPI_Finalize();
}
  

Ответ №1:

Вы хотите получать в new, а не amp; new, и отправлять из start, а не amp;start. Сила привычки, я знаю, тоже все время подводит меня.

Комментарии:

1. Это исправлено. Приветствия. Могу я просто спросить, почему это так?

2. Для буферов вы хотите отправить MPI указатель на то, где находятся данные (или куда вы хотите их переместить). send и new уже являются указателями на выделенную память; вы передали send как amp;(data[0][0][0]) , который является указателем на первый элемент в памяти и new является указателем на начало malloc()ed блока. Разыменование их означает, что теперь вы больше не передаете указатели на эти данные, а указываете на сами указатели. В этом случае оба этих указателя фактически находятся в стеке (как локальная переменная и аргумент), и поэтому в конечном итоге вы записываете все содержимое стека.