MPI Backwards Substitution error while slaves receives x from previous processes

MPI Backwards Substitution error while slaves receives x from previous processes

我想将向后替换顺序 C 代码转换为并行代码,但在 1 级大小接收数据时出现错误 MPI_Recv(prev_x, displacements[rank], MPI_FLOAT, rank-1, tag, MPI_COMM_WORLD, &status);。逻辑是进程之间的管道。

我的代码:

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



int main(int argc, char* argv[]){
    int i,j,N;
    float **a, *b;
    float *local_x, *prev_x, *total_proc_x;
    int tag = 100;
    
    //MPI variables
    int rank, size;
    MPI_Status status;
    
    MPI_Init(&argc, &argv);
    MPI_Comm_size(MPI_COMM_WORLD, &size);
    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
    
    
    
    if(argc != 2){
        if(rank == 0) printf("Using : %s <matrix_size>\n", argv[0]);
        return 0;
    }
    
    N = strtol(argv[1], NULL, 10);
    
    /* Allocate space for matrices */
    a = (float **) malloc ( N * sizeof ( float *) );
    for ( i = 0; i < N; i++) 
        a[i] = ( float * ) malloc ( (i+1) * sizeof ( float ) );
    b = ( float * ) malloc ( N * sizeof ( float ) );
    
    
    if(rank == 0){      
        srand ( time ( NULL));
        for (i = 0; i < N; i++) {
            b[i] = (float)rand()/(RAND_MAX*2.0-1.0);
            a[i][i] = 2.0+(float)rand()/(RAND_MAX*2.0-1.0);
            for (j = 0; j < i; j++) 
                a[i][j] = (float)rand()/(RAND_MAX*2.0-1.0);
            for (j=i; j<N; j++)
                a[i][j] = 0.0;
        } 
        
    }
    
    //broadcast data (a,b)
    MPI_Bcast(a, N*N, MPI_FLOAT, 0, MPI_COMM_WORLD);
    MPI_Bcast(b, N, MPI_FLOAT, 0, MPI_COMM_WORLD);
    
    
        
    int block_size = N/size;
    int *counts = (int *) malloc(size*sizeof(int));
    int *displacements = (int *) malloc(size*sizeof(int));
    int start, end;
    for(i=0; i<size; i++){
        start = 0;
        for(j=0; j<i; j++){
            start += block_size;
            if(size-(j+1) < N%size) start++;
        }
        end = start + block_size;
        if(size-(i+1) < N%size) end++;
        counts[i] = end - start;
        displacements[i] = start;
    }
        
    local_x = (float *) malloc(counts[rank]*sizeof(float));
    for(i=0; i<counts[rank]; i++){
        local_x[i] = 0.0;
    }
    prev_x = (float *) malloc(displacements[rank]*sizeof(float));
    
    if(rank == 0) printf("Size: %d\n", size);
    
    printf("Rank %d, Displacement: %d, Count: %d\n", rank, displacements[rank], counts[rank]);
    //calculation
    float sum;
    if(rank == 0){
        printf("Rank %d, OK\n", rank);
        for(i=0; i<counts[0]; i++){
            sum = 0.0;          
            for(j=0; j<i; j++){
                sum = sum + (local_x[j] * a[i][j]);
            }
            local_x[i] = (b[i] - sum) / a[i][i];
        }
        MPI_Send(local_x, displacements[rank+1], MPI_FLOAT, rank+1, tag, MPI_COMM_WORLD);
        printf("Process %d sent data to process %d\n", rank, rank+1);
    }
    
    
    if(rank != 0 && rank != (size-1)){
        printf("Rank %d, OK\n", rank);
        MPI_Recv(prev_x, displacements[rank], MPI_FLOAT, rank-1, tag, MPI_COMM_WORLD, &status);
        printf("Process %d received data from process %d", rank, rank-1);
        for(i=displacements[rank]; i<(displacements[rank] + counts[rank]); i++){
            sum = 0.0;
            //unowned rows
            for(j=0; j<displacements[rank]; j++){
                sum = sum + (prev_x[j] * a[i][j]);
            }
            
            //owned rows
            for(j=displacements[rank]; j<i; j++){
                sum = sum + (local_x[j-displacements[rank]] * a[i][j]);
            }
            
            local_x[i] = (b[i] - sum) / a[i][i];
        }
        
        //concatenate prev and local x
        total_proc_x = (float *) malloc((displacements[rank] + counts[rank])*sizeof(float));
        for(i=0; i<displacements[rank]; i++){
            total_proc_x[i] = prev_x[i];
        }
        
        for(i=0; i<counts[rank]; i++){
            total_proc_x[i+displacements[rank]] = local_x[i];
        }
        
        //send to next process
        MPI_Send(total_proc_x, displacements[rank+1], MPI_FLOAT, rank+1, tag, MPI_COMM_WORLD);
    }
    
    
    
    if(rank == (size-1)){
        printf("Rank %d, OK\n", rank);
        MPI_Recv(prev_x, displacements[rank], MPI_FLOAT, rank-1, tag, MPI_COMM_WORLD, &status);
        printf("Process %d received data from process %d", rank, rank-1);
        
        for(i=displacements[rank]; i<(displacements[rank] + counts[rank]); i++){
            sum = 0.0;
            //unowned rows
            for(j=0; j<displacements[rank]; j++){
                sum = sum + (prev_x[j] * a[i][j]);
            }
            
            //owned rows
            for(j=displacements[rank]; j<i; j++){
                sum = sum + (local_x[j-displacements[rank]] * a[i][j]);
            }
            
            local_x[i] = (b[i] - sum) / a[i][i];
        }
        
        //concatenate prev and local x
        float *total_proc_x = (float *) malloc((displacements[rank] + counts[rank])*sizeof(float));
        for(i=0; i<displacements[rank]; i++){
            total_proc_x[i] = prev_x[i];
        }
        
        for(i=0; i<counts[rank]; i++){
            total_proc_x[i+displacements[rank]] = local_x[i];
        }
        

        /* Print result */
        for (i = 0; i < N; i++) {
            for (j = 0; j <= i; j++)
                printf ("%f \t", a[i][j]);  
            printf ("%f \t%f\n", total_proc_x[i], b[i]);
        }
        
        /* Check result */
        for (i = 0; i < N; i++) {
            sum = 0.0;
            for (j = 0; j <= i; j++) 
                sum = sum + (total_proc_x[j]*a[i][j]);  
            if (fabsf(sum - b[i]) > 0.00001) {
                printf("%f != %f\n", sum, b[i]);
                printf("Validation Failed...\n");
            }
        }
    }
    
    MPI_Finalize();
    
    return 0;
    
}


输出:

$ mpicc -o backsub_mpi backsub_mpi.c
$ mpiexec -n 4 ./backsub_mpi 20

Rank 1, Displacement: 5, Count: 5
Rank 1, OK
Rank 3, Displacement: 15, Count: 5
Rank 3, OK
Size: 4
Rank 0, Displacement: 0, Count: 5
Rank 0, OK
Process 0 sent data to process 1
Rank 2, Displacement: 10, Count: 5
Rank 2, OK
-----------------------------------------------------------------------------
One of the processes started by mpirun has exited with a nonzero exit
code.  This typically indicates that the process finished in error.
If your process did not finish in error, be sure to include a "return
0" or "exit(0)" in your C code before exiting the application.

PID 4105 failed on node n0 (127.0.0.1) due to signal 11.
-----------------------------------------------------------------------------
mpirun failed with exit status 11

你的问题在于你如何分配矩阵

a = (float **) malloc ( N * sizeof ( float *) );
for ( i = 0; i < N; i++) 
    a[i] = ( float * ) malloc ( (i+1) * sizeof ( float ) );
  1. 你正试图分配一个三角数组,但你发送了它

    MPI_Bcast(a, N*N, MPI_FLOAT, 0, MPI_COMM_WORLD);

方阵。

  1. 由于a是一个数组或指针,实际的矩阵元素可能不在连续的内存中。

您需要将 double *a 分配为足够长的单个数组,然后进行一些索引转换以找出元素 i,j 进入该数组的位置。类似于 i*(i+1)/2+j.