2017-01-23 6 views
1

То, что я пытаюсь сделать, это сделать массив из 1s и 0s и разделить весь массив на 4 процесса (не имеет значения сколько 4 - это мой тестовый пример), и каждый процесс печатает свой ранг, длину массива и сам массив. Но когда я запускаю код, я получаю что-то вроде этого:По каким-то причинам мои другие процессы не получают данные из моего первого процесса (MPI in C)

Enter length and sequence length 
100 4 
1101000010110110101110101 
1110101001111100011100100 
1011100110011100001011010 
1000110101001000001000111 

Rank: 0 Length: 25 

Я не уверен, почему это происходит. По какой-то причине я не могу передать данные правильно и к другим процессам (я новичок в MPI)

Вот мой код:

#include "ore_header.h" 

int main(int argc, char** argv) { 

srand(time(NULL)); 

    int  my_rank, p; 
    int  total; 
    int  length; 
    int  seq_length; 
    void generate_sequence(int *arr, int n); 
    int  subsequence_check(int *arr,int n, int m); 


    MPI_Init(&argc, &argv); 
    MPI_Comm_size(MPI_COMM_WORLD, &p); 
    MPI_Comm_rank(MPI_COMM_WORLD, &my_rank); 

    MPI_Request  reqs[p]; 
    MPI_Status  stats[p]; 
    int  p_length; 
    int  p_total[p]; 
    int  *buf[p]; 
    if (my_rank == 0) { 
     printf("Enter length and sequence length\n"); 
     scanf("%d %d",&length, &seq_length); 
     p_length = length/p; 
     for (int i = 0; i < p; i++) { 
      buf[i] = (int*)malloc(p_length*sizeof(int)); 
      generate_sequence(buf[i], p_length); //Generates a sequence 
      MPI_Isend(&buf[i], p_length, MPI_INT, i, 0, MPI_COMM_WORLD, &reqs[i]); //Send each buffer to each sequence 
      MPI_Wait(&reqs[my_rank], &stats[my_rank]); //Wait for data to be sent 
     } 
    } 
    MPI_Irecv(&buf[my_rank], p_length, MPI_INT, 0, 0, MPI_COMM_WORLD, &reqs[my_rank]); //Receive Data from process 0 
    MPI_Wait(&reqs[my_rank], &stats[my_rank]); //Wait for communication to end 
    printf("\nRank: %d Length: %d\n",my_rank,p_length); 
    for (int i = 0; i < p_length; i++) { 
     printf("%d",buf[i]); 
    } 

    //tot = subsequence_check(buf,length,seq_length); 
    //printf("\n\nTotal: %d\n",tot); 
    MPI_Finalize(); 
    return (0); 
} 

UPDATE

Спасибо за корм назад Я установил вопросы и теперь он работает как задумано:

#include "ore_header.h" 

int main(int argc, char** argv) { 

    srand(time(NULL)); 

    int  my_rank, p; 
    int  total; 
    int  length; 
    int  flag; 
    int  seq_length; 
    void generate_sequence(int *arr, int n); 
    int  subsequence_check(int *arr,int n, int m); 


    MPI_Init(&argc, &argv); 
    MPI_Comm_size(MPI_COMM_WORLD, &p); 
    MPI_Comm_rank(MPI_COMM_WORLD, &my_rank); 


    int  p_length; 
    int  *buf[p]; 
    if (my_rank == 0) { 
     printf("Enter length and sequence length\n"); 
     scanf("%d %d",&length, &seq_length); 
     p_length = length/p; 
     for (int i = 0; i < p; i++) { 
      buf[i] = (int*)malloc(p_length*sizeof(int)); 
      generate_sequence(buf[i], p_length); 
      MPI_Send(buf[i], p_length, MPI_INT, i, 0, MPI_COMM_WORLD); 
      printf("Data sent to process %d\n", i); 
     } 
    } 
    MPI_Bcast(&p_length, 1, MPI_INT, 0, MPI_COMM_WORLD); 
    buf[my_rank] = (int*)malloc(p_length*sizeof(int)); 
    MPI_Status  stats[p]; 
    MPI_Request  reqs[p]; 
    MPI_Irecv(buf[my_rank], p_length, MPI_INT, 0, 0, MPI_COMM_WORLD, &reqs[my_rank]); 
    while(1) { 
     MPI_Test(&reqs[my_rank], &flag, &stats[my_rank]); 
     if (flag) break; 
    } 
    printf("\nData received on process: %d Length: %d\n",my_rank,p_length); 
    for (int i = 0; i < p_length; i++) { 
     printf("%d",buf[my_rank][i]); 
    } 
    printf("\n"); 

    //tot = subsequence_check(buf,length,seq_length); 
    //printf("\n\nTotal: %d\n",tot); 
    MPI_Finalize(); 
    return (0); 
} 

и вот мой результат:

Enter length and sequence length 
100 4 
0101100011001110110010011 
Data sent to process 0 
0010011010000001001010111 
Data sent to process 1 
0011111111101101100000111 
Data sent to process 2 
0000000100010011100001111 
Data sent to process 3 

Data received on process: 0 Length: 25 
0101100011001110110010011 

Data received on process: 1 Length: 25 
0010011010000001001010111 

Data received on process: 2 Length: 25 
0011111111101101100000111 

Data received on process: 3 Length: 25 
0000000100010011100001111 
+2

Что такое 'значение p_length', когда' MPI_Irecv'ing? – a3f

+0

, если я делаю длину n, тогда p_length является n \ p, где p - число процессов. – Malush

+1

Еще раз проверьте. :) – a3f

ответ

0

MPI_Isend() необходим указатель на буфер, а &buf[i] - указатель на указатель на буфер. Следовательно, вы могли бы попробовать MPI_Isend(buf[i],...?

Кроме того, запрос reqs[i] устанавливается в MPI_Isend(), но MPI_Wait() только проверяет завершение reqs[my_rank]. Таким образом, еще одна модификация может быть предложено:

MPI_Isend(buf[i], p_length, MPI_INT, i, 0, MPI_COMM_WORLD, &reqs[i]); //Send each buffer to each sequence 
MPI_Wait(&reqs[i], &stats[i]); //Wait for data to be sent 

Вызов MPI_Wait() сразу после MPI_Isend() кажется эквивалентно вызову MPI_Send(), в частности, если возвращаемый MPI_Status не тестировалась что-то вроде MPI_Test_cancelled(). В данном случае последовательные вызовы MPI_Wait() могут быть легко заменены одним вызовом MPI_Waitall() в конце цикла for.

Edit: вопрос @ A3F на значении p_length в MPI_Irecv() на рядах, кроме 0 остается в силе ...

+0

Эй, спасибо за ответ, можете объяснить, почему мой & buf [i] не работает? Я думал, что buf [i] удерживает значение указателя? или он удерживает адрес указателя? – Malush

+0

'buf [i]' является указателем на 'buf [i] [0]', первый элемент буфера: его значение является адресом 'buf [i] [0]'. Это именно то, что нужно MPI_Isend() '. Наоборот, '& buf [i]' является указателем на указатель 'buf [i]'. Его значением является адрес 'buf [i]', который не является первым элементом буфера. '& buf [i]' является указателем на указатель на буфер. Это один указатель слишком! – francis

+0

Получил. Благодаря! – Malush