【问题标题】:C MPI - Crash for no apparent reason - Program Received signal SIGSEGVC MPI - 无明显原因的崩溃 - 程序收到信号 SIGSEGV
【发布时间】:2014-07-06 10:12:44
【问题描述】:

我正在使用 MPICH2 1.0.6 的 linux 集群中运行一个程序(我实际上无法将其更新到 MPICH3,所以我坚持使用该版本)并且没有明显的原因该程序没有执行。

我使用mpicc -o prog prog.c -lm 编译它并使用mpiexec 执行

该程序是使用向量空间模型的层次凝聚聚类算法的实现。数据收集是一个n*m 数组(在程序DOC*MAXWORDS 中),它像PARTS=DOC/procs 一样划分为集群的节点,因此每个节点负责PARTS*MAXWORDS 数据。

在使用 gdb 和 ddd 在串行机器中调试时,我发现程序在代码的特定行中存在分段错误,我无法找到它的问题所在。看看吧。

while(iterations != DOC-k){//bigLoop

    iterations++;

    x=y=-1;
    pos1=pos2=node1=node2=-1;

    for(i=0;i<PARTS;i++){//ELEGXOS MEGISTOU TOPIKA
        if(max_array[i]>x){
            x=max_array[i];
            pos1=i;  
        }
        else if(max_array[i]==x){
            pos2=i;
        } //ELEGXOS META TO LOOP GIA OMOIOTHTES
    }

    if(max_array[pos1]!=max_array[pos2]){
        for(i=0;i<PARTS;i++){
            if(max_array[i]>max_array[pos2] && i!=pos1)
                pos2=1;
        }
    }

    if(MPI_Allgather(&x,1,MPI_DOUBLE,
            n_max,1,MPI_DOUBLE,MPI_COMM_WORLD) != MPI_SUCCESS) {
        printf("Allgather high valuer - error");
        exit(1);
    }

    for(i=0;i<procs;i++){
        if(n_max[i]>y){
           y=n_max[i];
           node1=i;
        }
        else if(n_max[i]==y){
            node2=i;
        }
    }
    for(i=0;i<MAXWORDS;i++){
        merger_one[i]=merger_two[i]=0;    
    }

    if(n_max[node1]==n_max[node2]){

        if(id==node1){
            for(i=0;i<MAXWORDS;i++){
                merger_one[i]=vector[node1*PARTS+pos1][i];
                last_one[i]=vector[(node1*PARTS)+texts_vectors[node1]][i];
             }
             size_one=size_of[pos1];

             nn_array[pos1]=nn_array[texts_vectors[node1]];
             max_array[pos1]=max_array[texts_vectors[node1]];
             size_of[pos1]=size_of[texts_vectors[node1]];
             texts_vectors[node1]--;
        }
        if(id==node2){
            for(i=0;i<MAXWORDS;i++){
                merger_two[i]=vector[node2*PARTS+pos2][i];
                last_two[i]=vector[(node2*PARTS)+texts_vectors[node2]][i];
            }

            j=pos2;
            pos2=pos1;
            pos1=j;

            size_two=size_of[pos2];

            nn_array[pos2]=nn_array[texts_vectors[node2]];
            max_array[pos2]=max_array[texts_vectors[node2]];
            size_of[pos2]=size_of[texts_vectors[node2]];
            texts_vectors[node2]--;
        }
    }
    else{

        node2=node1;

        if(id==node1){

            for(i=0;i<MAXWORDS;i++){

                merger_one[i]=vector[node1*PARTS+pos1][i];
                merger_two[i]=vector[node2*PARTS+pos2][i];

                last_one[i]=vector[(node1*PARTS)+texts_vectors[node1]][i];/*SIGSEV ERROR*/
                last_two[i]=vector[(node2*PARTS)+texts_vectors[node2]-1][i];

            }

            size_one=size_of[pos1];
            size_two=size_of[pos2];

            nn_array[pos1]=nn_array[texts_vectors[node1]];
            max_array[pos1]=max_array[texts_vectors[node1]];
            size_of[pos1]=size_of[texts_vectors[node1]];


            nn_array[pos2]=nn_array[texts_vectors[node2]-1];
            max_array[pos2]=max_array[texts_vectors[node2]-1];
            size_of[pos2]=size_of[texts_vectors[node2]-1];    

            texts_vectors[node1]=texts_vectors[node1]-2;
        }  
    }
    MPI_Bcast(&pos1, 1, MPI_INT,node1, MPI_COMM_WORLD);
    MPI_Bcast(&pos2, 1, MPI_INT,node2, MPI_COMM_WORLD);
    MPI_Bcast(&size_one, 1, MPI_INT,node1, MPI_COMM_WORLD);
    MPI_Bcast(&size_two, 1, MPI_INT,node2, MPI_COMM_WORLD);
    MPI_Bcast(merger_one, MAXWORDS, MPI_INT,node1, MPI_COMM_WORLD);
    MPI_Bcast(merger_two, MAXWORDS, MPI_INT,node2, MPI_COMM_WORLD);
    MPI_Bcast(last_one, MAXWORDS, MPI_INT,node1, MPI_COMM_WORLD);
    MPI_Bcast(last_two, MAXWORDS, MPI_INT,node2, MPI_COMM_WORLD);
    MPI_Allgather(&texts_vectors,1,MPI_INT,texts_vectors,1,MPI_INT,MPI_COMM_WORLD);

    for(i=0;i<MAXWORDS;i++){
        vector[node1*PARTS+pos1][i]=last_one[i];
        vector[node2*PARTS+pos2][i]=last_two[i];
    }

    Pmanager=PARTS+1;

    for(i=0;i<procs;i++){
        if(texts_vectors[i]<Pmanager)
        Pmanager=i;
    }

    texts_vectors[Pmanager]++;



    for(i=0;i<MAXWORDS;i++){
            x=merger_one[i]*size_one;
            y=merger_two[i]*size_two;

            vector[Pmanager*PARTS+texts_vectors[Pmanager]][i]=(x+y)/(size_one + size_two);
    }

    for(i=id*PARTS; i< (id+1)*texts_vectors[id]; i++){
       for(j=0;j<procs;j++){
           for(m=j*PARTS;m<j*PARTS+texts_vectors[j];m++){
               x=0;y=0;z=0;
               for(l=0; l < MAXWORDS; l++){
                   x+=vector[i][l]*vector[m][l];
                   y+=vector[i][l]*vector[i][l];
                   z+=vector[m][l]*vector[m][l];
               }
               if(i!=m){
                   if(y!=0 && z!=0){
                       sim_matrix[i-(PARTS*id)][m] = x / (sqrt(y) * sqrt(z) );
                   }
                   else{
                       sim_matrix[i-(PARTS*id)][m] = 0.0;
                   }
               }
           }
       }
   }
    for(i=0; i<texts_vectors[id]; i++){
        x=0.0;
        for(j=0;j<DOC;j++){
            if(sim_matrix[i][j]>x){
                nn_array[i]=j;
                max_array[i]=x=sim_matrix[i][j];
            }
        }
    }
}

在此之前创建数组并将数据输入到vector[i][j]

我使用 malloc 创建了数组:

int **vector = malloc(DOC * sizeof *vector);
for (i = 0; i < DOC; i++){
    vector[i] = malloc(MAXWORDS * sizeof **vector);
}
double **sim_matrix = malloc(PARTS * sizeof *sim_matrix);
for (i = 0; i < PARTS; i++)
    sim_matrix[i] = malloc(DOC * sizeof **sim_matrix);

int *list = malloc(WHOLE * sizeof(int));

int *nn_array = malloc(PARTS * sizeof(int));

double *max_array = malloc(PARTS * sizeof(double));

int *size_of = malloc(PARTS * sizeof(int));

double *n_max = malloc(procs * sizeof(double));

int *texts_vectors = malloc(procs * sizeof(int));

int *merger_one = malloc(MAXWORDS * sizeof(int));

int *merger_two = malloc(MAXWORDS * sizeof(int));

int *last_one = malloc(MAXWORDS * sizeof(int));

int *last_two = malloc(MAXWORDS * sizeof(int));

问题仍然存在的行:last_one[i]=vector[(node1*PARTS)+texts_vectors[node1]][i];/*SIGSEV ERROR*/ 也在 if 循环的第一部分中执行 if(n_max[node1]==n_max[node2]){ 但在这种情况下没有错误。

唯一对这个问题感到有点怀疑的是texts_vectors[i] 数组,它一直在计算节点内当前vector[i][j] 类型数据的数量。但即便如此,我认为我已经涵盖了它。

我真的希望有人可以看看这个,因为它真的很令人沮丧,需要完成。

如果您对正在发生的事情有更好的了解并想查看整个代码,请i pasted it into a pastezone. 干杯并提前致谢。

编辑:

事实证明,我通过数组text_vectors 传递的值超出了数组的边界。由于该值给出了最大值,因此对于数组中的实际最后一个位置,我应该减去 1。就是这样,串行 gdb 和 ddd 中没有分段错误。然而,这个程序现在不能运行超过 2 个节点。如果我在 4> 个节点中执行它,它会崩溃。

【问题讨论】:

  • 我不确定您是否正确创建了 vectorsim_matrix。这些行应该是:int **vector = malloc(DOC * sizeof(int*));for (i = 0; i &lt; DOC; i++) vector[i] = malloc(MAXWORDS * sizeof(int);,并为 sim_matrix 行完成了相应的更改。如果我理解正确,vectorsim_matrix 分别是整数和双精度的二维数组。至少对于sim_matrix,指向双精度数(4 字节)和双精度数(8 字节)的指针大小不同。我认为这不会解决您的问题,但我迟到了,稍后我会更好地查看您的代码。
  • 我会很感激的。至于数组的分配,我用这种方式已经有一段时间了,没有什么大问题。我可以快速更改并检查它。感谢您的宝贵时间
  • 天哪,对最后的评论感到抱歉。我刚刚意识到我是在取消引用,是的,在创建二维数组的方式上没有错
  • 这是一大堆代码,您的粘贴链接很快就会过期。这绝对违背了就 SO 提出问题的好方法。

标签: c debugging mpi


【解决方案1】:

这一行有多个错误:

MPI_Allgather(&texts_vectors,1,MPI_INT,texts_vectors,1,MPI_INT,MPI_COMM_WORLD);

首先,您提供了一个指向数据指针的指针,作为收集到所有操作的第一个参数。因此每个rank传输的值不是text_vectors的第一个元素,而是数据的内存地址(或64位little-endian LP64系统的地址的下半部分)。

其次,如果您通过从第一个参数的开头删除地址关闭运算符&amp; 来解决此问题,您将遇到另一个问题。 MPI 标准不允许MPI_Allgather 中的源缓冲区和目标缓冲区重叠。一些 MPI 实现不强制执行该要求,而是默默地执行The Right Thing (TM)。其他一些 MPI 实现将尝试使用 memcpy 复制数据并遇到 C 库问题(memcpy 不允许重叠缓冲区)。最后,一些 MPI 实现会给你一个关于重叠缓冲区的很好的错误消息并终止你的程序。

由于您发送的是单个整数元素,只需将值复制到临时变量中并将其地址用作第一个参数。

【讨论】:

  • 我确实使用了一个简单的整数来传递值,并且还使用了 `&texts_vectors[id] 并且出于某种原因我更改了它。感谢您指出了这一点。两只眼睛总是比一只眼睛好。错误仍然存​​在
  • &amp;texts_vectors[id] 也是错误的。它仍然指向位于接收缓冲区内且 MPI 标准禁止的位置。 MPI_Allgather 提供了一种特殊的就地模式,应改为使用 - 请参阅 the documentation(此模式来自 Open MPI,但也适用于 MPICH)。
  • 也许,但对于某些处决,它对我有用。不管怎样,我现在使用一个变量,但错误仍然存​​在。在else-loopif(id==node1) 表达式内部。我不断收到分段错误。
  • 它适用于您,因为您使用的是旧的 MPICH 版本。 SPEC MPI2007 中包含的其中一个程序存在类似问题,因此它无法在现代 MPI 实现或现代 Linux 系统上运行。无论如何,您可能应该使用一些并行调试器来检查您的代码是如何工作的(也可以使用printf 调试)。
猜你喜欢
  • 2018-04-09
  • 1970-01-01
  • 2015-03-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-09-09
相关资源
最近更新 更多