c# 使用MPI聚集时,memcpy参数内存范围重叠

kognpnkq  于 2023-04-18  发布在  C#
关注(0)|答案(1)|浏览(168)

我正在尝试用C语言使用MPI进行图像卷积。我的想法是将图像分成不同的块,让不同的进程进行不同的排名,然后将它们聚集在一个根进程中。
我对C语言很陌生,你能给我解释一下这个错误以及如何解决它吗?

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include <mpi.h>

#define IMAGE_IN "logo.pgm"
#define IMAGE_OUT "result.pgm"


/* function declarations */
int * read_image (char file_name[], int *p_h, int *p_w, int *p_levels);
void write_image (int *image, char file_name[], int h, int w, int levels);
int* convolve(int *image_in, int *image_out, int kernel[3][3], int height, int width,int first_row, int last_row,int chunk_size) {
    int i, j, x, y;
    int sum, max_val, min_val;
   
    /* initialize max_val and min_val */
    max_val = image_in[0];
    min_val = image_in[0];

    for (i = first_row; i < last_row; i++) {
        for (j = 1; j < width - 1; j++) {
            sum = 0;
            for (x = -1; x <= 1; x++) {
                for (y = -1; y <= 1; y++) {
                    sum += kernel[x+1][y+1] * image_in[(i+x)*width+(j+y)];
                }
            }
            /* update max_val and min_val */
            if (sum > max_val) {
                max_val = sum;
            }
            if (sum < min_val) {
                min_val = sum;
            }
            image_out[i*width+j] = sum;
        }
    }
    printf("min is:%d\n", min_val);
    printf("max is: %d\n",max_val);

    /* normalize pixel values */
    for (i = first_row; i < last_row; i++) {
        for (j = 1; j < width - 1; j++) {
            image_out[i*width+j] = 255 * (image_out[i*width+j] - min_val) / (max_val - min_val);           
        }
    }
    return image_out;
  }

int main(int argc, char *argv[])
{

  int i, j, h, w, levels ;
  struct timeval tdeb, tfin;
  int *image_in, *image_out;
  int my_rank;
  int num_procs;
  
  MPI_Init(&argc, &argv);
  MPI_Comm_size(MPI_COMM_WORLD, &num_procs);
  MPI_Comm_rank(MPI_COMM_WORLD, &my_rank);

  image_in = read_image (IMAGE_IN, &h, &w, &levels); 
  int chunk_size= h/num_procs;
  printf ("chunk size is %d \n", chunk_size);
  int first_row= my_rank* chunk_size+1;
  int last_row= first_row+ chunk_size-1;
  printf ("first row is %d \n", first_row);
  printf ("last row is %d \n", last_row);
  

  /* image processing (just a copy in this example) */
  gettimeofday(&tdeb, NULL);

  int kernel[3][3]={{0,-1,0},
                    {-1,5,-1},
                    {0,-1,0}};
                    
                    
  int *local_image =  malloc(chunk_size * w*sizeof(int));
  image_out = malloc (h*w*sizeof(int));
  
  local_image=convolve(image_in, image_out, kernel, chunk_size, w,first_row,last_row,chunk_size); 
  
  MPI_Gather(local_image, chunk_size*w,MPI_INT,image_out, h*w, MPI_INT, 0, MPI_COMM_WORLD);
  
  

  gettimeofday(&tfin, NULL);
  printf ("computation time (microseconds): %ld\n",  (tfin.tv_sec - tdeb.tv_sec)*1000000 + (tfin.tv_usec - tdeb.tv_usec));
  
  write_image (local_image, IMAGE_OUT, h, w, levels);
  
 
  MPI_Finalize(); 

  free (image_in);
  free (image_out); 

  return 0;
}

/*
* read an image from a file  and dynamic memory allocation for it
* param1 : name of the image file
* param2 : where to store the height
* param3 : where to store the weight
* param4 : where to store the number of levels
* return : address of the pixels
*/
int * read_image (char file_name[], int *p_h, int *p_w, int *p_levels){
  FILE *fin;
  int i, j, h, w, levels ;
  char buffer[80];
  int *image;

  /* open P2 image */
  fin = fopen (IMAGE_IN, "r");
  if (fin == NULL){
    printf ("file open error\n");
    exit(-1);
  } 
  fscanf (fin, "%s", buffer);
  if (strcmp (buffer, "P2")){
    printf ("the image format must be P2\n");
    exit(-1);
  }
  fgets (buffer, 80, fin);
  fgets (buffer, 80, fin);
  fscanf (fin, "%d%d", &w, &h);
  fscanf (fin, "%d", &levels);
  printf ("image reading ... h = %d w = %d\n", h, w);
  
  /* dynamic memory allocation for the pixels */
  image = malloc (h*w*sizeof(int));

  /* pixels reading */
  for (i = 0; i < h ; i++)
    for (j = 0; j < w; j++)
       fscanf (fin, "%d", image +i*w +j); 
  fclose (fin);

  *p_h = h;
  *p_w = w;
  *p_levels=levels;
  return image;
}
 

/*
* write an image in a file
* param1 : address of the pixels
* param2 : name of the image file
* param3 : the height
* param4 : the weight
* param5 : the number of levels
* return : void
*/

void write_image (int *image, char file_name[], int h, int w, int levels){
  FILE *fout;
  int i, j;

  /* open the file */
  fout=fopen(IMAGE_OUT,"w");
  if (fout == NULL){
    printf ("file opening error\n");
    exit(-1);
  }
  
  /* header write */
  fprintf(fout,"P2\n# test \n%d %d\n%d\n", w, h, levels);
  /* format P2, commentary, w x h points, levels */

  /* pixels writing*/
  for (i = 0; i < h ; i++)
    for (j = 0; j < w; j++)
       fprintf (fout, "%d\n", image[i*w+j]); 

  fclose (fout);
  return;
}

一切正常,直到出现这个错误。
在文件src/mpi/datatype/typeps/src/typep_yaksa_pack.c的第286行中Assert失败:假的
memcpy参数内存范围重叠,dst_= 0x 7 f56 ed 5 be 010 src_= 0x 7 f56 ed 5 be 010 len_=1557836
在节点0上中止(1):内部错误

nnt7mjpx

nnt7mjpx1#

你应该仔细看看MPI_Gather函数。首先,尝试注解掉它,看看错误是否消失。如果是这种情况,你可能会向MPI_Gather传递错误的参数。你得到的错误来自MPI库的某个地方,因为除了初始化之外,你在程序中使用的唯一函数是MPI_Gather

相关问题