2013-04-08 1 views
1

저는 지난 2 년 동안 인터넷에서 C++을 배웠고 마침내 MPI에 대해 알아봐야 할 필요성이 생겼습니다. 나는 stackoverflow와 나머지 인터넷 (http://people.sc.fsu.edu/~jburkardt/cpp_src/mpi/mpi.htmlhttps://computing.llnl.gov/tutorials/mpi/#LLNL 포함)을 수색했다. 나는 아래로 논리의 일부를 가지고 생각하지만, 나는 다음과 같은 주위에 내 머리를 포장 힘든 시간을 보내고 있습니다 : 위의MPI C++ 행렬 추가, 함수 인수 및 함수 반환

#include (stuff) 
using namespace std; 

vector<double> function(vector<double> &foo, const vector<double> &bar, int dim, int rows); 

int main(int argc, char** argv) 
{ 
    vector<double> result;//represents a regular 1D vector 
    int id_proc, tot_proc, root_proc = 0; 
    int dim;//set to number of "columns" in A and B below 
    int rows;//set to number of "rows" of A and B below 
    vector<double> A(dim*rows), B(dim*rows);//represent matrices as 1D vectors 

    MPI::Init(argc,argv); 
    id_proc = MPI::COMM_WORLD.Get_rank(); 
    tot_proc = MPI::COMM_WORLD.Get_size(); 

    /* 
    initialize A and B here on root_proc with RNG and Bcast to everyone else 
    */ 

    //allow all processors to call function() so they can each work on a portion of A 
    result = function(A,B,dim,rows); 

    //all processors do stuff with A 
    //root_proc does stuff with result (doesn't matter if other processors have updated result) 

    MPI::Finalize(); 
    return 0; 
} 

vector<double> function(vector<double> &foo, const vector<double> &bar, int dim, int rows) 
{ 
    /* 
    purpose of function() is two-fold: 
    1. update foo because all processors need the updated "matrix" 
    2. get the average of the "rows" of foo and return that to main (only root processor needs this) 
    */ 

    vector<double> output(dim,0); 

    //add matrices the way I would normally do it in serial 
    for (int i = 0; i < rows; i++) 
    { 
     for (int j = 0; j < dim; j++) 
     { 
      foo[i*dim + j] += bar[i*dim + j];//perform "matrix" addition (+= ON PURPOSE) 
     } 
    } 

    //obtain average of rows in foo in serial 
    for (int i = 0; i < rows; i++) 
    { 
     for (int j = 0; j < dim; j++) 
     { 
      output[j] += foo[i*dim + j];//sum rows of A 
     } 
    } 

    for (int j = 0; j < dim; j++) 
    { 
      output[j] /= rows;//divide to obtain average 
    } 

    return output;   
} 

코드는 개념을 설명하는 것입니다. 내 주된 관심사는 행렬 추가를 병렬 처리하는 것이지만, 내 마음을 두드리는 것은 다음과 같습니다.

1) 각 프로세서가 해당 루프의 일부에서만 작동하면 (당연히 프로세서 당 루프 매개 변수를 수정해야합니다) 어떤 명령 A의 모든 부분을 모든 프로세서가 메모리에 가지고있는 업데이트 된 단일 A로 병합하는 데 사용합니까? 내 생각 엔 각 프로세서가 A의 부분을 다른 모든 프로세서로 보내는 일종의 Alltoall을 수행해야하지만, 어떻게하면 (예를 들어) 행 3이 프로세서 3에서 작업했는지를 다른 프로세서의 행 3을 덮어 쓰게하고, 우연히 행 1이 아닙니다.

I는, 함수() 내부에 Alltoall을 사용하는 모든 프로세서() 함수에 단계 허용해야 또는 I 사용) (기능 분리 할 수 ​​않으면 2) ...

if (id_proc == root_proc) 
{ 
    result = function(A,B,dim,rows); 
} 
... 및 function() 함수는 모든 병렬 처리를 처리합니다. 어리석은 것처럼 들리는 바, 하나의 프로세서 (브로드 캐스트 포함)에서 많은 작업을하고, 많은 시간을 소모하는 루프를 병렬화하려고합니다. 개념적으로 간단하게 코드를 유지하려고하므로 결과를 얻고 계속 진행할 수 있습니다.

3) 평균화 부분에서는 평행 화하려는 경우 축소 명령을 사용할 수 있습니다. 맞습니까?

또한, 옆으로 : Bcast()를 호출하여 차단하는 방법이 있습니까? 내 모든 프로세서를 동기화하는 데 사용하고 싶습니다 (라이브러리를 향상시키는 것은 옵션이 아닙니다). 그렇지 않다면 나는 Barrier()와 함께 갈 것이다. 이 질문에 대한 답변과 지난 2 년간 프로그래밍 방법을 배운 stackoverflow 커뮤니티에 감사드립니다. :)

답변

1

1) 찾고있는 기능은 MPI_Allgather입니다. MPI_Allgather를 사용하면 각 프로세서에서 행을 보내고 모든 프로세서에서 결과를 수신 할 수 있습니다.

2) 그렇습니다. 일부 기능은 사용하실 수 있습니다. MPI 기능은 커뮤니케이터와 함께 작동하므로 별도의 커뮤니케이터를 만들어야합니다. C++ 바인딩에서 어떻게 구현되는지 모르지만 C 바인딩은 MPI_Comm_create 함수를 사용합니다.

3) 예, MPI_Allreduce를 참조하십시오.

aside : Bcast는 해당 프로세스에 할당 된 보내기/받기 작업이 완료 될 때까지 프로세스를 차단합니다. 모든 프로세서가 작업을 마칠 때까지 기다리고 싶다면 Barrier()를 사용해야합니다. 왜이 작업을해야하는지 알지 못합니다.

추가 참고 : C++ 바인딩은 가치가 떨어지며 사용법에 대한 구체적인 예는 찾을 수 없으므로 사용하지 않는 것이 좋습니다. Boost MPI는 C++ 바인딩을 원한다면 사용할 라이브러리이지만 모든 MPI 함수를 포함하지는 않습니다.

+0

도움 주셔서 감사합니다. 1)에 대한 응답으로, 모체가 모든 프로세서 사이에서 균등하게 나뉘어 질 것이라고 보장 할 수 없기 때문에, 수집하는 벡터의 길이가 달라집니다. MPI_Allgatherv를 사용해야한다는 것을 읽었습니다. 내가 무엇을 할 수 있는지 알아볼 게. 다시 한 번 감사드립니다! –