2013-06-20 9 views
0

我想寫我自己的MPI函數,它將計算矢量中的最小數字並將其廣播到所有進程。我將這些進程當作一棵二叉樹,並在從葉子移動到根時找到最小值。然後我通過它的孩子從根發送信息給葉子。但是我得到的,當我試圖接收來自左子最小值分段故障在短短4流程執行從0排名過程等級1(工藝等級3)3MPI自己的代碼來找到一個向量中的最小值

void Communication::ReduceMin(double &partialMin, double &totalMin) 
{ 
    MPI_Barrier(MPI_COMM_WORLD); 
    double *leftChild, *rightChild; 
    leftChild = (double *)malloc(sizeof(double)); 
    rightChild = (double *)malloc(sizeof(double)); 
    leftChild[0]=rightChild[0]=1e10; 
    cout<<"COMM REDMIN: "<<myRank<<" "<<partialMin<<" "<<nProcs<<endl; 
    MPI_Status *status; 
    //MPI_Recv from 2*i+1 amd 2*i+2 
    if(nProcs > 2*myRank+1) 
    { 
     cout<<myRank<<" waiting from "<<2*myRank+1<<" for "<<leftChild[0]<<endl; 
     MPI_Recv((void *)&leftChild[0], 1, MPI_DOUBLE, 2*myRank+1, 2*myRank+1, MPI_COMM_WORLD, status);    //SEG FAULT HERE 
     cout<<myRank<<" got from "<<2*myRank+1<<endl; 
    } 
    if(nProcs > 2*myRank+2) 
    { 
     cout<<myRank<<" waiting from "<<2*myRank+2<<endl; 
     MPI_Recv((void *)rightChild, 1, MPI_DOUBLE, 2*myRank+2, 2*myRank+2, MPI_COMM_WORLD, status); 
     cout<<myRank<<" got from "<<2*myRank+1<<endl; 
    } 
    //sum it up 
    cout<<myRank<<" finding the min"<<endl; 
    double myMin = min(min(leftChild[0], rightChild[0]), partialMin); 
    //MPI_Send to (i+1)/2-1 
    if(myRank!=0) 
    { 
     cout<<myRank<<" sending "<<myMin<<" to "<<(myRank+1)/2 -1 <<endl; 
     MPI_Send((void *)&myMin, 1, MPI_DOUBLE, (myRank+1)/2 - 1, myRank, MPI_COMM_WORLD); 
    } 

    double min; 
    //MPI_Recv from (i+1)/2-1 
    if(myRank!=0) 
    { 
     cout<<myRank<<" waiting from "<<(myRank+1)/2-1<<endl; 
     MPI_Recv((void *)&min, 1, MPI_DOUBLE, (myRank+1)/2 - 1, (myRank+1)/2 - 1, MPI_COMM_WORLD, status); 
     cout<<myRank<<" got from "<<(myRank+1)/2-1<<endl; 
    } 
    totalMin = min; 
    //MPI_send to 2*i+1 and 2*i+2 
    if(nProcs > 2*myRank+1) 
    { 
     cout<<myRank<<" sending to "<<2*myRank+1<<endl; 
     MPI_Send((void *)&min, 1, MPI_DOUBLE, 2*myRank+1, myRank, MPI_COMM_WORLD); 
    } 
    if(nProcs > 2*myRank+2) 
    { 
     cout<<myRank<<" sending to "<<2*myRank+1<<endl; 
     MPI_Send((void *)&min, 1, MPI_DOUBLE, 2*myRank+2, myRank, MPI_COMM_WORLD); 
    } 
} 

PS:我知道我可以使用

MPI_Barrier(MPI_COMM_WORLD); 
MPI_Reduce((void *)&partialMin, (void *)&totalMin, 1, MPI_DOUBLE, MPI_MIN, 0, MPI_COMM_WORLD); 
MPI_Bcast((void *)&totalMin, 1, MPI_DOUBLE, 0, MPI_COMM_WORLD); 

但我想寫我自己的代碼的樂趣。

+1

其實您只需要一個'M PI_Allreduce'行。我不確定C++的範圍規則是如何工作的,但可能是'&min'返回'min'函數的地址,而不是具有相同名稱的局部變量的地址。 –

+0

如果您是在編寫自己的函數而不是像@HristoIliev提到的那樣使用內置的函數,那麼您可能需要提供更多的調試信息。你有沒有嘗試使用gdb/ddd/TotalView來更好地瞭解它爲什麼會出現分段? –

+0

感謝您的信息。我確實使用gdb,並且我知道它是seg。在MPI Recv語句中出現故障。我沒有深入挖掘。由於我在一個項目中遲到了,我確實使用了MPI_Allreduce()。我會在一段時間內恢復自己的實施。 – Shank

回答

0

錯誤在於您在接收調用中使用status參數的方式。而是傳遞一個MPI_Status實例的地址,您只需通過一個未初始化的指針,並導致崩潰:既然你不

MPI_Status status; 
... 
MPI_Recv((void *)&leftChild[0], 1, MPI_DOUBLE, 2*myRank+1, 2*myRank+1, 
     MPI_COMM_WORLD, &status); 

MPI_Status *status; // status declared as a pointer and never initialised 
... 
MPI_Recv((void *)&leftChild[0], 1, MPI_DOUBLE, 2*myRank+1, 2*myRank+1, 
     MPI_COMM_WORLD, status); // status is an invalid pointer here 

你應該改變你的代碼檢查代碼中的所有狀態,您可以在所有調用中簡單地通過MPI_STATUS_IGNORE

MPI_Recv((void *)&leftChild[0], 1, MPI_DOUBLE, 2*myRank+1, 2*myRank+1, 
     MPI_COMM_WORLD, MPI_STATUS_IGNORE); 
相關問題