0

ベラード関数を実行して pi を小数点以下 1 万桁まで計算する mpi プログラムを作成しようとしています。プログラムを実行すると、次のエラーが表示されます。オンラインおよびopenMpi Webサイトで検索を行ったところ、問題はnullポインターのようですが、コードを調べたところ見つかりませんでした。

エラーは次のとおりです: シグナル:セグメンテーション違反(11) シグナル:アドレスがマップされていません(1) アドレスで失敗: (nil)

誰でもヌルポインタを見ることができますか?

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

#define PRECISION 10000


float minus_one,one,two,three,four,five,six,seven,eight,nine,ten,   
    thirty_two,sixty_four,two_five_six,one_zero_two_four,
    two_pow_six,recip_two_pow_six;


float *pi;
int rank,size;

void init(){
    printf("\nstarted init function");
    minus_one = -1.0;
    one = 1.0;
    two = 2.0;
    three = 3.0;
    four = 4.0;
    five = 5.0;
    six = 6.0;
    seven = 7.0;
    eight = 8.0;
    nine = 9.0;
    ten = 10.0;
    thirty_two = 32.0;
    sixty_four = 64.0;
    two_five_six = 256.0;
    one_zero_two_four = 1024.0;
    two_pow_six = pow(two,6);
    recip_two_pow_six = one/two_pow_six;

    pi = 0;
    printf("\nended init function");
    return;
}

float *bellard(int start, int end,int rank){
    float *terms;
    float t,t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,
        t13,t14,t15,t16,t17,tx,ty,tz;

    int offset = rank;
    double start_k = start;
    double end_k = end;
    start_k = offset * (PRECISION /size);
    end_k = (offset+1) * (PRECISION/size);
    terms=0;

    int k = start_k;

    while( (k<PRECISION) && (k<end_k)){
        t1 = k;
        t2 = t1*ten;
        t3 = t2+one;
        t4 = two_five_six/t3;
        t5 = t2+nine;
        t6 = one/t5;
        t7 = t2+three;
        t8 = sixty_four/t7;
        t9 = four*t1;
        t10 = t9+one;
        t11 = thirty_two/t10;
        t12 = t2+five;
        t13 = four/t12;
        t14 = t2+seven;
        t15 = four/t14;
        t16 = t9+three;
        t17 = one+t16;

        t = t4+t6;
        t = t-t8;
        t = t-t11;
        t = t-t13;
        t = t-t15;
        t = t-t17;

        tx = pow(minus_one,k);
        ty = pow(one_zero_two_four,k);
        tz = tx/ty;
        *terms = tz*t;

        //pi = pi+terms;
        k = k+1;
    }
        return terms;
}

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


    int i;
    MPI_Status status;
    MPI_Init(&argc, &argv);
    MPI_Comm_size(MPI_COMM_WORLD, &size);
    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
    int elementsCount = 10000/(size-1);
    float *workerPi;
    float *tmpPi=0;

    init(); //initialise variables
    printf("\nim here 1");
    if(rank == 0)
    {
        for(i=1; i < size; i++){
            printf("\nin recv loop");           
            MPI_Recv(tmpPi,PRECISION,MPI_FLOAT,i,1,MPI_COMM_WORLD,&status);
            *pi=*pi+*tmpPi;
        }
    }else{

        //int i;

        int start,end,slice,workers;
        workerPi = malloc(sizeof(int)*elementsCount);
        workers = size-1;
        slice = 10000/workers;
        start = (rank-1)*slice;
        end = start+slice;

        printf("\nWorker %d processing data %d to %d\n",rank,start,end);

        workerPi = bellard(start,end,rank);
        printf("\nworker finished pi");

        MPI_Send(workerPi,slice,MPI_FLOAT,0,1,MPI_COMM_WORLD);
        printf("\nworker sent stuff");

    }

    MPI_Finalize();

    return 0;
}
4

1 に答える 1

2

bellard関数内では、termsへのポインタとして宣言されていますfloat

float *terms;

nullそして数行下でゼロ(別名)に初期化されます

terms=0;

while ループの終わりに向かって、逆参照されます。

*terms = tz*t;

ステートメント*termsはヌル ポインター逆参照であり、クラッシュします。tz*t基本的に、有効なメモリ アドレスではないメモリ アドレス 0 に結果を格納するよう求めています。

修正は、float ( ) へのポインターではなく、termsとして宣言して使用することです。floatfloat*

于 2013-11-09T17:38:22.023 に答える