Можно ли удалить динамически размещенный массив в главном ранге после того, как я рассеял его по всем процессам в MPI? - PullRequest
0 голосов
/ 24 июня 2019

Я пытался написать код об итерационном решателе jacobi, используя динамический массивы. Мой вопрос: уместно ли удалять массив после рассеяние на все процессы. (я говорю о b_local, A_local)

double *b_local;
double *A_local;
int size;
MPI_Comm_size(MPI_COMM_WORLD, &size);   
int rank;
MPI_Comm_rank(MPI_COMM_WORLD,&rank);    
if (rank==0){
    b_local=new double[n];
    A_local=new double[n*n];
    cout<<"Enter talerance,number of iterations"<<endl;
    cin>>tol;
    cin>>max_iter;
    //Create A and scatter it to all process
    CreateMatrix(A_local);
    //Create b and scatter it to all process    
    CreateVector(b_local);

}
//data init
double *A=new double[n*n/size];
double *b=new double[n/size];
double *x_out=new double[n/size];
//brocast tol,max_iter to all processes
MPI_Bcast(&tol,1,MPI_DOUBLE,0,MPI_COMM_WORLD);//send to all processes
MPI_Bcast(&max_iter,1,MPI_INT,0,MPI_COMM_WORLD);    
//scatter vector b.Each process takes n/size
MPI_Scatter(b_local,n/size,MPI_DOUBLE,b,n/size,MPI_DOUBLE,0,MPI_COMM_WORLD);//here n_local cause we have only one column
//scatter it to all processes
MPI_Scatter(A_local,(n/size)*n,MPI_DOUBLE,A,(n/size)*n,MPI_DOUBLE,0,MPI_COMM_WORLD);//n_local*n--->number of elements in n/size rows
if (rank==0){
 delete [] b_local;
 delete [] A_local;
}

Ответы [ 2 ]

2 голосов
/ 24 июня 2019

Для кода, который вы разместили, трудно сказать, нормально ли удалять массивы, потому что некоторые части отсутствуют.

В целом, однако, MPI_Scatter и MPI_Bcast блокируют вызовы.Это означает, что код будет продолжаться, только если эти вызовы функций были успешно завершены.(Это не значит, что все процессы завершены.) MPI может все же завершить некоторые вещи под капотом, но, что касается вашего кода, это сделано.Поэтому безопасно удалить данные, которые вы поместили в эти функции, потому что MPI больше не обращается к ним после вызова.

Sidenote:

На это уже указывалосьв комментариях, но я еще раз подчеркиваю: гораздо проще использовать умные указатели для управления памятью, чем использовать raw new и delete.Вы даже можете хранить массивы в стиле C!Например:

#include <memory>

...

std::unique_ptr<double[]> b = std::make_unique<double[]>(n/size);

//at the callsites use b.get() instead of b

Этот подход позволяет компилятору автоматически удалять точку (с ее содержимым), если она больше не используется.Кроме того, вы не можете забыть позвонить delete плюс исключения обрабатываются правильно.

В качестве альтернативы вы можете просто использовать std::vector и передать указатель .data() на MPI.

Добавление:

Если вы планируете некоторое время использовать MPI и не любите бороться с интерфейсом C, вам следует рассмотреть возможность использования библиотеки оболочки C ++, такой как Boost.MPI .

0 голосов
/ 24 июня 2019

MPI_Scatter - операция блокировки, которая завершается, как только вызов возвращается. Таким образом, после возврата MPI_Scatter вы можете повторно использовать буфер и, в частности, удалить его. Напротив, MPI_Iscatter является неблокирующей операцией. Вы должны дождаться завершения, прежде чем безопасно использовать буфер.

...