2012-06-19 3 views
2

В настоящее время я работаю над проектом, где мне нужно реализовать параллельный алгоритм 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; 
} 

Я очень ценю обратную связь!

ответ

1

Вы используете массивы/указатели для массивов в неправильном направлении. Например, вы объявляете массив как двойной комплексный блок [N], который является прекрасным (хотя и редко, в большинстве случаев лучше использовать malloc), а затем вы получаете его через MPI_Recv (&). Однако «block» уже является указателем на этот массив, поэтому, написав «& block», вы передаете указатель указателя на MPI_Recv. Это не то, чего он ожидает. Если вы хотите использовать нотацию «&», вы должны написать & блок [0], который даст вам указатель на первый элемент блока-массива.

+0

Я решил взять мой код в другом направлении, но разъяснение о «&» обозначениях и указателях было очень полезно. Спасибо! – Muttonchop

+2

На самом деле существует тонкая разница между именами массивов и указателями. Поскольку 'block' - это имя массива,' block', '& block' и' & block [0] 'дают тот же адрес (попробуйте!), а если 'block' - указательная переменная, то' & block', то должен указывать адрес, в котором хранится значение указателя. Так что ваш ответ просто неправильный. –

+0

Вау, спасибо за разъяснение! Я всегда думал, что char * a и char a [] эквивалентны, но это не так! – timos

1

Вы пробовали отлаживать свой код? Это может быть болью в параллельной настройке, но она может сказать вам, где именно она терпит неудачу, и обычно также почему.

Если вы используете Linux или OS X, вы можете запустить свой код следующим образом в командной строке:

mpirun -np 4 xterm -e gdb -ex run --args ./yourprog yourargs 

где я предполагаю, yourprog это имя вашей программы и yourargs являются любой командой которые вы хотите передать.

Эта команда будет запускать четыре окна xterm. Каждый xterm, в свою очередь, запускает gdb, как указано опцией -e. gdb выполнит команду run, указанную опцией -ex, и запустит ваш исполняемый файл с заданными параметрами, как указано --args.

Что вы получаете, это четыре окна с четырьмя экземплярами вашей программы параллельно с MPI. Если какой-либо из экземпляров сбой, gdb расскажет вам, где и почему.

+0

С открытым MPI вы также можете использовать встроенную поддержку для запуска 'xterm':' mpirun -np 4 -xterm -1 gdb ... 'или даже' mpirun -np 4 -xterm -1 \! gdb ... ', чтобы предотвратить автоматическое закрытие' xterm' после выхода gdb. –

Смежные вопросы