Ошибка при попытке использовать Mpi recv: ошибка сегментации сигнала

#c

#c

Вопрос:

🙂

Я получил тревожный вопрос, касающийся программы mpi. Идея такова: каждый процесс (подчиненный) отправляет данные ведущему, чтобы вычислить фрактал Мандельброта.

Во-первых, каждая подчиненная отправленная точка и ит-работник. Затем они отправили строку, и это сработало!

Но теперь я пытаюсь заставить их отправлять блок строк (предположим, 5 строк, то есть подматрицу).

Моя идея состоит в том, чтобы объединить эти пять строк в одну строку. Мастер получает первую «новую» строку, но не для остальных O_o. Я обеспокоен.

Я получаю для остальных (> 1): ошибка сегментации сигнала, код сигнала: адрес не сопоставлен, ошибка при адресе

Пожалуйста, помогите мне! Поскольку прошло много времени, я искал: (

PS: я француз (вот почему мой английский плохой)

//the whole table to be used in a master //int table[NX*NY]; //int count =0; if (rank == 0) { int res; int line[MAXY MAXY 1]; int block[5*(MAXY MAXY 1)]; int count = 0; /* Begin User Program - the master */ //MPI_Recv(amp;line, MAXY MAXY 1, MPI_INT,MPI_ANY_SOURCE, DATATAG, MPI_COMM_WORLD, amp;status); MPI_Recv(amp;block, 5*(MAXY MAXY 1), MPI_INT,MPI_ANY_SOURCE, DATATAG, MPI_COMM_WORLD, amp;status); printf("sizeof of datablock received is = %d n",sizeof(block)/sizeof(block[0])); recvd = status.MPI_SOURCE; printf("i have received blockdata from %d n",recvd); /* remplissage du case */ for(i = -MAXX; i <= MAXX; i ) { for(j = -MAXY; j <= MAXY; j ) { cases[i MAXX][j MAXY] = block[count%(MAXY MAXY 1)]; //printf("j'ai fait un bloc[count], pas crediblen"); count ; } } dump_ppm("mandel.ppm", cases); printf("Fini.n"); } else { /* On est l'un des fils */ /* for the block;let's suppose each son send 5 rows*/ double x, y; int i, j, res, rc, rank,count; //int line[MAXY MAXY 1]; int block[5*(MAXY MAXY 1)]; count = 0; MPI_Comm_rank(MPI_COMM_WORLD, amp;rank); for(i = -MAXX; i <= MAXX; i ) { for(j = -MAXY; j <= MAXY; j ) { x = 2 * i / (double)MAXX; y = 1.5 * j / (double)MAXY; res = mandel(x, y); //line[j MAXY] = res; block[count] =res; if (count % (5*(MAXY MAXY 1)) == 0){ //we send each five rows MPI_Send(amp;block,5*(MAXY MAXY 1), MPI_INT, 0, DATATAG, MPI_COMM_WORLD); printf("me slave %d, have sent datablock to mastern",rank); printf("sizeof of datablock sent is = %dn",sizeof(block)/sizeof(block[0])); } count ; } //MPI_Send(amp;line, MAXY MAXY 1 , MPI_INT, 0, DATATAG, MPI_COMM_WORLD); } } MPI_Finalize(); return 0; }

Ответ №1:

Функции MPI_Recv() необходим адрес буфера, куда будут приниматься данные. Это то же самое для MPI_Send() . Поскольку int block[5*(MAXY MAXY 1)] является массивом, block указывает на первый элемент массива block[0] : это требуемый адрес. С другой стороны, amp;block указывает на block : это похоже на указатель на указатель на int . Но значение amp;block не является адресом первого элемента массива!

Следовательно, не могли бы вы попробовать:

 int block[5*(MAXY MAXY 1)]
...
MPI_Send(block,5*(MAXY MAXY 1), MPI_INT, 0, DATATAG, MPI_COMM_WORLD);
...
MPI_Recv(block, 5*(MAXY MAXY 1), MPI_INT,MPI_ANY_SOURCE, DATATAG, MPI_COMM_WORLD, amp;status);
  

Что эквивалентно:

 int block[5*(MAXY MAXY 1)]
...
MPI_Send(amp;block[0],5*(MAXY MAXY 1), MPI_INT, 0, DATATAG, MPI_COMM_WORLD);
...
MPI_Recv(amp;block[0], 5*(MAXY MAXY 1), MPI_INT,MPI_ANY_SOURCE, DATATAG, MPI_COMM_WORLD, amp;status);
  

Что, если вам нужно отправить одно целое int a число? Адрес a ( amp;a ) может быть предоставлен MPI_Send() , как выполняется во многих примерах, посвященных MPI_Send() :

 int a=42;
MPI_Send(amp;a,1, MPI_INT, 0, DATATAG, MPI_COMM_WORLD);
  

Наконец, убедитесь, что MPI_Send() вызывается столько раз, сколько MPI_Recv() . Действительно, в опубликованном вами коде, MPI_Recv() вызывается корневым процессом только один раз, в то время как каждый некорневой процесс отправит сообщение корню. Следовательно, программа будет работать для двух процессов, и, скорее всего, произойдет сбой, если будет использовано больше процессов или если будет использован один процесс.