MPI_BYTE - это особый описатель типа; который не описывает тип данных для конкретного языка программирования (в Си он ближе всего к unsigned char). Использование MPI_BYTE означает, что содержимое соответствующего массива НЕ ДОЛЖНО подвергаться НИКАКИМ преобразованиям - и на приемной, и на передающей стороне массив будет иметь одну и ту же длину и одинаковое ДВОИЧНОЕ представление.
Зачем функциям упаковки/распаковки требуется описатель области связи? Описатель, помимо прочего, несет в себе информацию о распределении подсоединенных к области связи задач по процессорам и компьютерам. Если процессоры одинаковые, или задачи выполняются на одном и том же процессоре, данные просто копируются, иначе происходит их преобразование в/из формата XDR (eXternal Data Representation - разработан фирмой Sun Microsystems, используется в Интернете для взаимодействия разнотипных машин). Учтите, что коммуникаторы у функций упаковки/распаковки и у соответствующей функции передачи/приема должны совпадать, иначе произойдет ошибка ;
По мере того как во временный буфер помещаются данные или извлекаются оттуда, MPI сохраняет текущую позицию в переменной, которая в приведенном примере названа bufPos. Не забудьте проинициализировать ее нулем перед тем как начинать упаковывать/извлекать. Естественно, что передается она не по значению, а по ссылке. Первый же аргумент - "адрес временного буфера" - во всех вызовах остается неизменным ;
В примере НЕКОРРЕКТНО выбран размер временного буфера: использовалось НЕВЕРНОЕ предположение, что в XDR-формате данные займут места не больше, чем в формате используемого ветвью процессора; или что XDR-преобразование заведомо не будет применено. Правильным же решением будет для определения необходимого размера временного буфера на приемной стороне использовать связку MPI_Probe / MPI_Get_count / MPI_Recv, а на передающей - функцию MPI_Pack_size:
int bufSize = 0;
void *tempBuf;
MPI_Pack_size( 1, MPI_INT, MPI_COMM_WORLD, &bufSize );
MPI_Pack_size( 4, MPI_FLOAT, MPI_COMM_WORLD, &bufSize );
MPI_Pack_size( 8, MPI_CHAR, MPI_COMM_WORLD, &bufSize );
tempBuf = malloc( bufSize );
/* ... теперь можем упаковывать, не опасаясь переполнения */
Однако и вариант 2 замедляет работу: по сравнению с единственным вызовом memcpy на SMP-машине или одном процессоре занудная упаковка/распаковка - дело весьма небыстрое!
Вариант 3 ("жульнический"). Если есть уверенность, что одни и те же типы данных в обеих ветвях приложения имеют одинаковое двоичное представление, то:
Передача: MPI_Send( &s, sizeof(s), MPI_BYTE, ... );
Прием: MPI_Recv( &s, sizeof(s), MPI_BYTE, ... );
А все, чем чреват такой подход, подробно перечислено в предыдущей главе.
Do'stlaringiz bilan baham: |