В настоящее время я работаю над проектом, где мне нужно реализовать параллельный алгоритм fft с использованием openmpi. У меня есть компиляционная часть кода, но когда я запускаю ее по кластеру, я получаю ошибки сегментации.Segfault при запуске openmpi
У меня есть свои суждения о том, где все идет не так, но я не думаю, что у меня достаточно понимания указателей и ссылок, чтобы иметь возможность сделать эффективное исправление.
Первый фрагмент, который может пойти не так, заключается в передаче массивов вспомогательным функциям. Я считаю, что либо мой цикл несовместим, либо я не понимаю, как передать эти указатели и вернуть нужные мне вещи.
Второе возможное место будет находиться в действительных командах mpi_Send/Recv. Я отправляю тип, который не поддерживается типами данных openmpi c, поэтому я использую тип mpi_byte для отправки необработанных данных. Является ли это жизнеспособным вариантом? Или я должен искать альтернативу этому методу.
/* function declarations */
double complex get_block(double complex c[], int start, int stop);
double complex put_block(double complex from[], double complex to[],
int start, int stop);
void main(int argc, char **argv)
{
/* Initialize MPI */
MPI_Init(&argc, &argv);
double complex c[N/p];
int myid;
MPI_Comm_rank(MPI_COMM_WORLD, &myid);
//printf("My id is %d\n",myid);
MPI_Status status;
int i;
for(i=0;i<N/p;i++){
c[i] = 1.0 + 1.0*I;
}
int j = log(p)/log(2) + 1;
double q;
double complex z;
double complex w = exp(-2*PI*I/N);
double complex block[N/(2*p)]; // half the size of chunk c
int e,l,t,k,m,rank,plus,minus;
int temp = (log(N)-log(p))/log(2);
//printf("temp = %d", temp);
for(e = 0; e < (log(p)/log(2)); e++){
/* loop constants */
t = pow(2,e); l = pow(2,e+temp);
q = n/2*l; z = cpow(w,(complex)q);
j = j-1; int v = pow(2,j);
if(e != 0){
plus = (myid + p/v)%p;
minus = (myid - p/v)%p;
} else {
plus = myid + p/v;
minus = myid - p/v;
}
if(myid%t == myid%(2*t)){
MPI_Recv((char*)&c,
sizeof(c),
MPI_BYTE,
plus,
MPI_ANY_TAG,
MPI_COMM_WORLD,
&status);
/* transform */
for(k = 0; k < N/p; k++){
m = (myid * N/p + k)%l;
c[k] = c[k] + c[k+N/v] * cpow(z,m);
c[k+N/v] = c[k] - c[k + N/v] * cpow(z,m);
printf("(k,k+N/v) = (%d,%d)\n",k,k+N/v);
}*/
printf("\n\n");
/* end transform */
*block = get_block(c, N/v, N/v + N/p + 1);
MPI_Send((char*)&block,
sizeof(block),
MPI_BYTE,
plus,
1,
MPI_COMM_WORLD);
} else {
// send data of this PE to the (i- p/v)th PE
MPI_Send((char*)&c,
sizeof(c),
MPI_BYTE,
minus,
1,
MPI_COMM_WORLD);
// after the transformation, receive data from (i-p/v)th PE
// and store them in c:
MPI_Recv((char*)&block,
sizeof(block),
MPI_BYTE,
minus,
MPI_ANY_TAG,
MPI_COMM_WORLD,
&status);
*c = put_block(block, c, N/v, N/v + N/p - 1);
//printf("Process %d send/receive %d\n",myid, plus);
}
}
/* shut down MPI */
MPI_Finalize();
}
/* helper functions */
double complex get_block(double complex *c, int start, int stop)
{
double complex block[stop - start + 1];
//printf("%d = %d\n",sizeof(block)/sizeof(double complex), sizeof(&c)/sizeof(double complex));
int j = 0;
int i;
for(i = start; i < stop+1; i++){
block[j] = c[i];
j = j+1;
}
return *block;
}
double complex put_block(double complex from[], double complex to[], int start, int stop)
{
int j = 0;
int i;
for(i = start; i<stop+1; i++){
to[i] = from[j];
j = j+1;
}
return *to;
}
Я очень ценю обратную связь!
Я решил взять мой код в другом направлении, но разъяснение о «&» обозначениях и указателях было очень полезно. Спасибо! – Muttonchop
На самом деле существует тонкая разница между именами массивов и указателями. Поскольку 'block' - это имя массива,' block', '& block' и' & block [0] 'дают тот же адрес (попробуйте!), а если 'block' - указательная переменная, то' & block', то должен указывать адрес, в котором хранится значение указателя. Так что ваш ответ просто неправильный. –
Вау, спасибо за разъяснение! Я всегда думал, что char * a и char a [] эквивалентны, но это не так! – timos