я имею double A[B_ROWS][B_COLUMNS];
в C API я использовал stufflike:
MPI_Isend(&A[low_bound][0], (upper_bound - low_bound) * A_COLUMNS, MPI_DOUBLE, i, MASTER_TO_SLAVE_TAG + 2, MPI_COMM_WORLD, &request);
а также
MPI_Recv(&A[low_bound][0], (upper_bound - low_bound) * A_COLUMNS, MPI_DOUBLE, 0, MASTER_TO_SLAVE_TAG + 2, MPI_COMM_WORLD, &status);
Сейчас с наддувом :: mpi Я попробую:
world.isend(i, TO_SLAVE_TAG + 2, &A[low_bound][0], (upper_bound - low_bound) * A_COLUMNS);
а также
world.recv(0, TO_SLAVE_TAG + 2, &A[low_bound][0], (upper_bound - low_bound) * A_COLUMNS);
но мое приложение постоянно выходит из строя с такими вещами, как:
rank 1 in job 10 master_39934 caused collective abort of all ranks
exit status of rank 1: killed by signal 11
что значит seg fault
Обратите внимание, что оригинальное приложение C работало как нужно, и все, что я в настоящее время изменил, — это использование api, а не какой-либо логики.
Итак, как правильно посылать массивы в стиле 2d C через boost :: mpi?
Если предположить, что мое слепое предположение верно, а то, что вы напечатали выше, является точным, то размер A
не имеет ничего общего с A_COLUMNS
(вместо, A
имеет B_COLUMNS
). Если это так, то приведенный ниже код исправит ошибку «несинхронизировано»:
template<typename World, typename T>
void isend( World& w, int dest, int tag, T const* t, size_t n = 1) {
world.isend(dest, tag, &t, n);
}
template<typename World, typename T, size_t aSize>
void isend( World& w, int dest, int tag, T const (*arr1)[aSize], size_t n = 1) {
world.isend(dest, tag, &(*arr)[0], n*aSize);
}
template<typename World, typename T, size_t aSize, size_t bSize>
void isend( World& w, int dest, int tag, T const (*arr2)[aSize][bSize], size_t n = 1) {
world.isend(dest, tag, &(*arr)[0][0], n*aSize*bSize);
}
template<typename World, typename T>
void recv( World& w, int dest, int tag, T* t, size_t n = 1) {
world.recv(dest, tag, &t, n);
}
template<typename World, typename T, size_t aSize>
void recv( World& w, int dest, int tag, T (*arr1)[aSize], size_t n = 1) {
world.recv(dest, tag, &(*arr)[0], n*aSize);
}
template<typename World, typename T, size_t aSize, size_t bSize>
void recv( World& w, int dest, int tag, T (*arr2)[aSize][bSize], size_t n = 1) {
world.recv(dest, tag, &(*arr)[0][0], n*aSize*bSize);
}
Приведенный выше код для одно- и двухмерных массивов определит, сколько копий T вы действительно хотите отправить, вместо того, чтобы поддерживать его вручную.
Это даже работает на ломтики, как &A[low_bound], upper_bound-lower_bound
,
Одна вещь, о которой вы, возможно, захотите быть осторожной, это пройти через конец массива. Вполне возможно, что ваш C-код прошел конец массива, но там не было ничего важного, поэтому он выжил. В коде C ++ у вас может быть объект, и вы умрете вместо того, чтобы выжить.
Другим подходом может быть написание функции, которая принимает верхнюю и нижнюю границы для среза, например так:
template<typename World, typename T, size_t N>
void isend_slice( World& w, int dest, int tag, T const (&t)[N], size_t start=0, size_t end=N ) {
Assert( end <= N && start < end );
isend(world, dest, tag, &(t[start]), end-start);
}
template<typename World, typename T, size_t N>
void recv_slice( World& w, int dest, int tag, T (&t)[N], size_t start=0, size_t end=N ) {
Assert( end <= N && start < end );
recv(world, dest, tag, &(t[start]), end-start);
}
в этом случае вы передаете массив напрямую, а затем говорите, где хотите начать и закончить чтение. Преимущество состоит в том, что я проверяю, что массив действительно содержит данные для отправки или место для данных, чтобы прибыть.
(Эти две функции полагаются на функции выше)
В распределенной ситуации вы захотите создать механизм регистрации для ваших утверждений, который будет описательным.
Вот пример использования вышеуказанного кода:
int array[10];
int array2[10][10];
isend(world, dest, tag+0, &int(7)); // tag is an int
isend(world, dest, tag+1, &array); // tag+1 is a 10 int array
isend(world, dest, tag+2, &array2); // tag+2 is a 100 int array
isend(world, dest, tag+1, &(array2[5])); // tag+1 is a 10 int array
isend_slice(world, tag+3, 0, array2, 7, 11); // asserts, but its a 40 int array
и то же самое для recv.
Других решений пока нет …