2015-02-23 89 views
-2

编辑:最新的代码发布,最后一个警告......警告说明在行97“recvbuffer”(在MPI_Send中)未定义。但在此之前,我在所有过程中定义了recvbuffer [totalnums]。为什么程序不能保持我在到达代码的mergesort部分时定义的recvbuffer数组变量?“未定义的变量”警告,但在所有进程中定义了变量

#include <stdio.h> 
#include <stdlib.h> 
#include <limits.h> 
#include <math.h> 
#include <mpi.h> 
#define TAG 25 


int compare(const void *a, const void *b) {      /* Comparison function for qsort */ 
    int var1, var2, ret; 
    var1 = *(const int *)a; 
    var2 = *(const int *)b; 
    if (var1 == var2) { 
     ret = 0; 
    } 
    else { 
     ret = (var1 < var2) ? -1 : 1; 
    } 
    return ret; 
} 



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

    int rank, process;        /* Variable declarations */ 

    MPI_Init(&argc, &argv);        /* Initialize MPI */ 
    MPI_Comm_size(MPI_COMM_WORLD, &process); 
    MPI_Comm_rank(MPI_COMM_WORLD, &rank); 

    int size, origsize, h, i, j, k, p, q, r, s, v, x, z, chunk;   /* Variable declarations */ 
    int totalnums;         /* Variable declarations */ 

    if (rank != 0) {        /* Receive totalnums value from process 0 for all processes */ 
     MPI_Recv(&totalnums, 1, MPI_INT, 0, TAG, MPI_COMM_WORLD, MPI_STATUS_IGNORE); 
     int recvbuffer[totalnums];      /* Create recvbuffer array for all processes except root */ 
     qsort(recvbuffer, chunk, sizeof(int), compare); 
    } 

    if (rank == 0) { 

     FILE *infilename;       /* Initialize input file variable */ 

     infilename = fopen(argv[1], "r");     /* Read input file */ 

     if (infilename == 0) {       /* Check whether read-in file exists */ 
      printf("File not found.\n"); 
      return 1; 
     } 

     fscanf(infilename, "%d", &size);     /* Obtain total number of items in file */ 

     totalnums = size; 

     while (totalnums % process != 0) {     /* Obtain total number of spots to allocate in array */ 
      totalnums += 1; 
     } 


     int A[totalnums];       /* Declare array size */ 

     for (i = 0; i<size; i++) {      /* Create array A[] from file using process 0 until end of file reached*/ 
      fscanf(infilename, "%d", &A[i]); 
     } 

     origsize = size;       /* Store original value for total numbers in file */ 

     for (x = size; x < totalnums; x++) {     /* Fill in empty spots at end of array with INT_MAX numbers */ 
      A[x] = INT_MAX; 
     } 

     fclose(infilename);       /* Close the incoming file */ 

     MPI_Bcast(&origsize, 1, MPI_INT, 0, MPI_COMM_WORLD);   /* Broadcast origsize and send totalnums to all processes */ 
     for (h = 1; h < process; h++) { 
      MPI_Send(&totalnums, 1, MPI_INT, h, TAG, MPI_COMM_WORLD); 
     } 

     int recvbuffer[totalnums];      /* Create recvbuffer array in process 0 */ 

     chunk = totalnums/process;      /* Calculate chunk size for each process */ 

     MPI_Scatter(A, chunk, MPI_INT, recvbuffer, chunk, MPI_INT, 0, MPI_COMM_WORLD);     /* Send select chunk to each process */ 
     qsort(recvbuffer, chunk, sizeof(int), compare);    /* Perform sort on each chunk in individual processes */ 
    } 

    int step, mergebuffer[totalnums], combinedbuffer[totalnums];   /* Create step and mergebuffer array variables */ 

    printf("stage 2 complete.\n"); 

    for (z = 0; z <= ((process-1)/2); z++) {     /* Start mergesort */ 
     for (step = 1; step < process; step = 2*step) { 
      if (rank % (2*(2 << z)*step) != 0) { 
       MPI_Send(recvbuffer, (2 << z)*chunk, MPI_INT, rank-(step*(2 << z)), TAG, MPI_COMM_WORLD);  /* Send elements to partner process */ 
       break; 
      } 
      else { 
       MPI_Recv(mergebuffer, (2 << z)*chunk, MPI_INT, rank+(step*(2 << z)), TAG, MPI_COMM_WORLD, MPI_STATUS_IGNORE); /* Receive elements from partner process and store in mergebuffer */ 
       p = 0; 
       q = 0; 
       r = 0; 
       while (p != (2 << z)*chunk && q != (2 << z)*chunk) {     /* Start combining and sorting buffers */ 
        if (recvbuffer[p] > mergebuffer[q] || q == (2 << z)*chunk) { 
         combinedbuffer[r] = recvbuffer[p]; 
         r++; 
         p++; 
        } 
        else if (recvbuffer[p] <= mergebuffer[q] || p == (2 << z)*chunk) { 
         combinedbuffer[r] = mergebuffer[q]; 
         r++; 
         q++; 
        } 
       } 
       v = 0; 
       while (v != (2 << z)*chunk) {       /* Copy combinedbuffer into recvbuffer to start next iteration */ 
        recvbuffer[v] = combinedbuffer[v]; 
       } 
      } 
     } 
     printf("get to here?\n"); 
    } 

    if (rank == 0) { 

     FILE *outfilename;       /* Initialize output file variable */ 
     outfilename = fopen(argv[2], "w");     /* Create output file */ 

     fprintf(outfilename, "Sorted array of %d elements:\n", origsize); /* Print first line of output file */ 
     s = 0; 
     for (j = 0; j < (totalnums/10); j++) {     /* Create multiple rows of 10 numbers per row */ 
      for (k = 0; k < 10; k++) {     /* Cycle 10 times */ 
       if (recvbuffer[s] != INT_MAX) {    /* Print next number to file until first INT_MAX entry reached */ 
        fprintf(outfilename, "%d ", recvbuffer[s]); 
       } 
       s++;      /* Increase value to proceed through entire list */ 
      } 
      fprintf(outfilename, "\n\n");     /* Print two returns at end of each 10 number row */ 
     } 
     fclose(outfilename);       /* Close the outgoing file */ 

    printf("Stage 4 complete.\n"); 
    } 

    MPI_Finalize();         /* Finalize MPI */ 

    printf("\n"); 

    return 0; 

} 
+0

了解如何使用调试器;投资将获得丰厚回报。 – 2015-02-23 17:05:50

+0

即使没有调试器,也可以通过插入'printf()'提示找到导致错误的行。分而治之:在中间开始,消除一半或其他等 – 2015-02-23 17:11:58

+0

哪些排名segfaults? – 2015-02-23 17:43:13

回答

0

回答评论MPI_Bcast有问题。你正在调用这个函数三次。

int MPI_Bcast(void *buffer, int count, MPI_Datatype datatype, int root, MPI_Comm comm) 

第一个参数需要一个缓冲区的地址。最后的三个调用的是这个

MPI_Bcast(recvbuffer, totalnums, MPI_INT, 0, MPI_COMM_WORLD); 

,因为你通过缓冲区(和含蓄它的地址),它看起来相当不错,而且它的大小。但是,你的前两个电话都是

MPI_Bcast(origsize, 1, MPI_INT, 0, MPI_COMM_WORLD); 
MPI_Bcast(totalnums, 1, MPI_INT, 0, MPI_COMM_WORLD); 

在这两种情况下,你传递一个缓冲区1元,但你是不是经过缓冲地址。虽然我不完全按照你的代码,我建议尝试这样的:

MPI_Bcast(&origsize, 1, MPI_INT, 0, MPI_COMM_WORLD); 
MPI_Bcast(&totalnums, 1, MPI_INT, 0, MPI_COMM_WORLD); 

注意添加&指示的地址。在第一条语句中,你传递了一个数组,所以它的地址隐含在语句中,而不是单个整数。

+0

非常感谢!我已经为所有字符串添加了“&”,并且通过这一点似乎可以正常工作(使用printf进行检查)。但你的方式使用原来的“recvbuffer”,因为它的工作原理也是如此。非常感谢!我还在第114行和第119行收到关于“寻找(int),收到(int *)”的错误 - 在打印到outfile的代码末尾。有任何想法吗?我是否删除了第115行中的“&”?试图打印“\ n \ n”(双重退货)如何?还有另一种方法可以做到这一点,或者我可以从其他地方得到一个错误进行到这一点? – 2015-02-23 18:30:23

+0

不应在'fprintf(outfilename,“%d元素的排序数组:\ n”,&origsize);'或打印'recvbuffer [s]'时使用'&'。虽然为什么你为'MPI_Bcast()'等使用'int origsize'和'int totalnums'等,这是超出我的。 – 2015-02-23 18:53:21

+0

非常感谢您的帮助,我确实删除了recvbuffer前的&,但没有看到您提到的另一个。出于某种原因,警告行号码未与代码中的位置对齐。现在看起来好多了,只有3到4个警告才能理清。不坏我不认为我的第一个C程序构建:)再次感谢您的帮助! – 2015-02-23 19:02:42