MPI_Isend и MPI_Irecv, кажется, вызывают тупик - PullRequest
2 голосов
/ 08 апреля 2011

Я использую неблокирующую связь в MPI для отправки различных сообщений между процессами.Тем не менее, я, кажется, захожу в тупик.Я использовал PADB ( см. Здесь ) для просмотра очередей сообщений и получил следующий вывод:

1:msg12: Operation 1 (pending_receive) status 0 (pending)
1:msg12: Rank local 4 global 4
1:msg12: Size desired 4
1:msg12: tag_wild 0
1:msg12: Tag desired 16
1:msg12: system_buffer 0
1:msg12: Buffer 0xcaad32c
1:msg12: 'Receive: 0xcac3c80'
1:msg12: 'Data: 4 * MPI_FLOAT'
--
1:msg32: Operation 0 (pending_send) status 2 (complete)
1:msg32: Rank local 4 global 4
1:msg32: Actual local 4 global 4
1:msg32: Size desired 4 actual 4
1:msg32: tag_wild 0
1:msg32: Tag desired 16 actual 16
1:msg32: system_buffer 0
1:msg32: Buffer 0xcaad32c
1:msg32: 'Send: 0xcab7c00'
1:msg32: 'Data transfer completed'
--
2:msg5: Operation 1 (pending_receive) status 0 (pending)
2:msg5: Rank local 1 global 1
2:msg5: Size desired 4
2:msg5: tag_wild 0
2:msg5: Tag desired 16
2:msg5: system_buffer 0
2:msg5: Buffer 0xabbc348
2:msg5: 'Receive: 0xabd1780'
2:msg5: 'Data: 4 * MPI_FLOAT'
--
2:msg25: Operation 0 (pending_send) status 2 (complete)
2:msg25: Rank local 1 global 1
2:msg25: Actual local 1 global 1
2:msg25: Size desired 4 actual 4
2:msg25: tag_wild 0
2:msg25: Tag desired 16 actual 16
2:msg25: system_buffer 0
2:msg25: Buffer 0xabbc348
2:msg25: 'Send: 0xabc5700'
2:msg25: 'Data transfer completed'

Это, похоже, показало, что отправка завершена, но всеожидающие получения (выше - только небольшая часть журнала для значения тега 16).Однако как это может произойти?Конечно, отправка не может завершиться без завершения соответствующего приема, так как в MPI все отправления и получения должны совпадать.По крайней мере, я так думал ...

Кто-нибудь может дать какие-то идеи?

Я могу предоставить код, который я использую для этого, но, конечно, Isend и Irecv должны работать независимо от того, чтов порядке их вызова, при условии, что MPI_Waitall вызывается в самом конце.

Обновление: Код доступен на в этой сущности

Обновление: Я сделал различные модификации в коде, но он все еще не работает должным образом.Новый код в тот же гист , и вывод, который я получаю в этот гист .У меня есть ряд вопросов / проблем с этим кодом:

  1. Почему выходные данные из заключительного цикла (печать всех массивов) перемежаются с остальными выходными данными, когда у меня естьMPI_Barrier () перед тем, как удостовериться, что вся работа была выполнена перед распечаткой?

  2. Возможно / целесообразно отправлять сообщения от 0 до 0 - будет ли это работатьОК?(конечно, при условии получения правильного совпадения).

  3. Я получаю много очень странных длинных чисел в выводе, что, как я полагаю, является некоторой проблемой перезаписи памятиили проблема размеров переменных.Интересно то, что это должно быть результатом обмена данными MPI, потому что я инициализирую new_array значением 9999,99, и связь, очевидно, вызывает его изменение на эти странные значения.Есть идеи, почему?

В целом кажется, что происходит некоторая часть транспонирования (биты матрицы кажутся транспонированными ...), но определенно не все из них - это страннономера, которые выходят, которые волнуют меня больше всего!

1 Ответ

4 голосов
/ 08 апреля 2011

При использовании MPI_Isend и MPI_Irecv вы должны быть уверены, что не изменяете буферы, пока не дождетесь завершения запроса, и вы определенно нарушаете это. Что если у вас все получатели перейдут во вторую матрицу вместо того, чтобы делать это на месте?

Кроме того, global_x2 * global_y2 - это ваш тег, но я не уверен, что он будет уникальным для каждой пары отправки-получения, которая может испортить ситуацию. Что произойдет, если вы переключите его на отправку тега (global_y2 * global_columns) + global_x2 и получение тега (global_x2 * global_columns) + global_y2.

Edit: Что касается вашего вопроса о выводе, я предполагаю, что вы тестируете это, запуская все свои процессы на одной машине и просто просматривая стандартный вывод. Когда вы делаете это таким образом, ваш вывод странным образом буферизируется терминалом, хотя весь код printf выполняется перед барьером. Есть два способа обойти это. Вы можете либо напечатать отдельный файл для каждого процесса, либо вы можете отправить свои выходные данные в виде сообщений для процесса 0 и позволить ему выполнить всю фактическую печать.

...