2015-02-23 123 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