Я работаю над преобразованием своей программы для использования произвольной точности и поэтому начал использовать MPFR. У меня была собственная структура MPI, содержащая мои данные в исходном коде. Теперь, когда я преобразовал свои данные в mpfr_t
, я не знаю, как создать эту структуру в MPI.
typedef struct job_s {
int f;
mpfr_t l,t,r,b;
} jobs;
MPI_Datatype MPI_JOBS_TYPE;
MPI_Type_create_struct(
5,
(int []) {1, sizeof(mpfr_t), sizeof(mpfr_t), sizeof(mpfr_t), sizeof(mpfr_t)},
(MPI_Datatype []) {offsetof(jobs,f), offsetof(jobs,l), offsetof(jobs,t), offsetof(jobs,r), offsetof(jobs, b)},
(MPI_Datatype []) {MPI_INT, MPI_BYTE, MPI_BYTE, MPI_BYTE, MPI_BYTE},
&MPI_JOBS_TYPE
);
MPI_Type_commit(&MPI_JOBS_TYPE);
Эта структура затем отправляется позже с помощью
jobs send;
/* set the objects of the struct to whatever using MPFR */
MPI_Send(&send, 1, MPI_JOBS_TYPE, reqRank, 0, MPI_COMM_WORLD);
Я не уверен, куда идти дальше. Я понимаю, что это очень неправильно, поскольку MPI не может определить размер структуры, поскольку я еще даже не установил точность (это вообще так работает?). Буду признателен за любую помощь! Спасибо.
Обновлено:
Я так близко, но что-то все еще не так с экспортом, отправкой, получением или импортом переменных mpfr_t
. Я успешно могу упаковать f
, отправить, получить и распаковать!
char * mpfr_buf;
size_t mpfr_buf_size;
char buf [3000];
pos = 0;
MPI_Pack(&f, 1, MPI_INT, buf, 3000, &pos, MPI_COMM_WORLD);
stream = open_memstream(&mpfr_buf, &mpfr_buf_size);
for(i = 0; i < 4; ++i)
mpfr_fpif_export(stream, bounds[i]);
MPI_Pack(stream, 3000-sizeof(int), MPI_BYTE, buf, 3000, &pos, MPI_COMM_WORLD);
print_bounds(bounds, "s");
MPI_Send(buf, pos, MPI_PACKED, reqRank, 0, MPI_COMM_WORLD);
fclose(stream);
f += 1;
и на принимающей стороне
pos = 0;
char buf [3000];
MPI_Recv(buf, 3000, MPI_PACKED, PARENT, 0, MPI_COMM_WORLD, &status);
int msgSize = 0;
MPI_Get_count(&status, MPI_BYTE, &msgSize);
printf("msg size %d\n", msgSize);
MPI_Unpack(buf, 3000, &pos, &f, 1, MPI_INT, MPI_COMM_WORLD);
printf("Worker %d recived frame %d\n", rank, f);
char streambuf [3000];
MPI_Unpack(buf, 3000, &pos, streambuf, msgSize - pos, MPI_BYTE, MPI_COMM_WORLD);
stream = fmemopen(streambuf, 3000, "r");
for(i = 0; i < 4; ++i){
mpfr_fpif_import(bounds[i], stream);
}
fclose(stream);
Я получаю мусор для первых трех импортируемых файлов, а для последнего я SIGBART с ошибкой get_str.c:157: MPFR assertion failed: size_s1 >= m
. Еще раз любая помощь приветствуется! Спасибо.
К сожалению, передавать числа MPFR не так просто, как типы данных MPI, не нарушая при этом исходную или двоичную совместимость. Проблема в том, что mpfr_t
— это структура с элементом типа указатель, поэтому вы не можете просто сериализовать ее как чистую последовательность байтов. Вам необходимо зарегистрировать тип данных MPI, соответствующий внутренней структуре MPFR, и использовать его при определении типа данных MPI для вашей собственной структуры.
Но вы не можете создать только один тип MPI, соответствующий любому экземпляру mpfr_t
. MPI не поддерживает погоню за указателем, и, учитывая, что элемент указателя в mpfr_t
может указывать на местоположения с произвольным и, скорее всего, различным смещением в каждом экземпляре (создание структурированного типа MPI работает со смещениями от адреса буфера), вам необходимо создать отдельный тип данных MPI для каждой переменной типа mpfr_t
. Это возможно, но очень далеко от оптимального, потому что:
mpfr_t
Портативное решение — использовать функции MPFR для Ввода и вывода, и, в частности, две экспериментальные функции, которые читают и записывают экземпляры MPFR из и в потоки C FILE. Что вам нужно сделать, так это создать поток памяти с помощью open_memstream
и использовать mpfr_fpif_export
для записи в него переносимых представлений l
, t
, r
и b
, а затем упаковать полученные байты в буфер MPI с помощью MPI_Pack
. Вам также придется вручную упаковать f
. На стороне получателя распакуйте f
с помощью MPI_Unpack
, затем распакуйте массив байтов и откройте его как поток памяти с помощью fmemopen
в режиме чтения, затем используйте mpfr_fpif_import
, чтобы прочитать из него четыре значения. Поскольку представления могут иметь разный размер, вам следует использовать MPI_Probe
на стороне получателя, чтобы сначала получить фактический размер сообщения, а затем выделить достаточно большой буфер для MPI_Recv
.
Если экспериментальный характер экспорта и импорта FPIF вас как-то сбивает с толку, используйте строковый ввод/вывод.
Я обновил свой пост, указав, что он довольно близок к этому, но все еще не уверен, что происходит не так.
@LucianChauvin, вы распаковываете 1 байт сообщения вместо всего сериализованного потока. Используйте MPI_Get_count(&status, MPI_BYTE, &msgSize)
, чтобы узнать размер сообщения. msgSize - pos
(после первой распаковки) — размер упакованного массива байт, который станет потоком вашей памяти.
Обратите внимание, что MPI_Pack
не кодирует информацию о типе или размере в сообщении, и вы должны указать правильный размер распаковки MPI_Unpack
.
Хорошо. У меня все заработало, спасибо за помощь. Сейчас это происходит довольно медленно, но пусть будет так.
@LucianChauvin, у тебя есть идеи, что делает его медленным? Такие инструменты, как Score-P, могут оказаться полезными.
@Hristo_Ilieve Я пришел к выводу, что изменение скорости не имеет ничего общего с тем, что мы здесь сделали. Спасибо за помощь.
Я попробую! Спасибо.