MPI_Status status;
int count;
MPI_Recv( … , MPI_INT, … , &status );
MPI_Get_count( &status, MPI_INT, &count );
/* … теперь count содержит количество принятых ячеек */
Обратите внимание, что аргумент-описатель типа у MPI_Recv и MPI_Get_count должен быть одинаковым, иначе, в зависимости от реализации в count вернется неверное значение; или произойдет ошибка времени выполнения.
Константы-пустышки включают:
-
MPI_COMM_NULL;
-
MPI_DATATYPE_NULL;
-
MPI_REQUEST_NULL.
Константа неопределенного значения используется в процедуре MPI_Comm_Split и имеет имя MPI_UNDEFINED.
Константы глобальных операций используются в процедурах коллективного взаимодействия процессов для указания типа выполняемой операции. Данные константы включают:
-
MPI_MAX;
-
MPI_MIN;
-
MPI_SUM;
-
MPI_PROD.
Константы, определяющие любой процесс/идентификатор, используются для обозначения
-
MPI_ANY_SOURCE;
-
MPI_ANY_TAG.
В стандарте MPI существует несколько предопределенных типов, среди них:
-
MPI_Status — структура; атрибуты сообщений; содержит три обязательных поля:
-
MPI_Source (номер процесса отправителя);
-
MPI_Tag (идентификатор сообщения);
-
MPI_Error (код ошибки);
-
MPI_Request — системный тип; идентификатор операции посылки-приема сообщения;
-
MPI_Comm — системный тип; идентификатор группы (коммуникатора);
-
MPI_COMM_WORLD — зарезервированный идентификатор группы, состоящей их всех процессов приложения.
3.8 Латентность и пропускная способность
3.8.1 Понятия латентности и пропускной способности
Латентность — это время между инициированием передачи данных в процессе посылки и прибытия первого байта в процессе приема. Латентность часто зависит от длины посылаемых сообщений. Ее значение может изменяться в зависимости от того, послано ли большое количество маленьких сообщений или нескольких больших сообщений.
Пропускная способность — это величина, обратная времени, необходимого для передачи одного байта. Пропускная способность обычно выражается в мегабайтах в секунду. Пропускная способность важна, когда передаются сообщения больших размеров.
Для улучшения характеристик латентности и пропускной способности необходимо:
-
подсчитать кол-во каналов передачи данных между процессами при разработке крупномодульных приложений;
-
использовать архивацию данных для больших сообщений, а также использовать описываемые типы данных вместо MPI_PACK и MPI_UNPACK если возможно;
-
использовать при возможности коллективные операции; это устраняет вызов MPI_Send и MPI_RECV каждый раз при коммуникации процессов;
-
определять номер принимающего процесса при вызове подпрограммы MPI; использование MPI_ANY_SOURCE может увеличивать латентность;
-
использовать MPI_RECV_INIT и MPI_STARTALL вместо вызова MPI_Irecv в цикле в случаях, когда запросы/прием не могут быть выполнены сразу.
Например, вы написали программу, содержащую фрагмент:
j = 0
for (i=0; i
if (i==rank) continue;
MPI_Irecv(buf[i], count, dtype, i, 0, comm, &requests[j++]);
}
MPI_Waitall(size-1, requests, statuses);
Предположим, что одна из итераций с вызовом MPI_IRECV не завершилась перед следующей итерацией цикла. В этом случае, MPI пробует выполнить оба запроса. Это может продолжаться, приводя к большему времени ожидания. Чтобы избежать этого, можно переписать эту часть кода так:
j = 0
for (i=0; i
if (i==rank) continue;
MPI_Recv_init(buf[i], count, dtype, i, 0, comm,
&requests[j++]);
}
MPI_Startall(size-1, requests);
MPI_Waitall(size-1, requests, statuses);
В этом случае все итерации с вызовом MPI_RECV_INIT выполняются только один раз при вызове MPI_STARTALL. При таком подходе вы не получите дополнительного времени ожидания при использовании MPI_Irecv и может улучшить латентность приложения.
3.8.2 Выбор подпрограмм/функций MPI
Для достижения наименьшей латентности и наибольшей пропускной способности сообщений для синхронной передачи «точка-точка», используйте блокирующие функции MPI MPI_Send и MPI_RECV. Для асинхронной передачи, используйте неблокирующие функции MPI MPI_Isend и MPI_IRECV.
При использовании блокирующих функций, старайтесь избегать ожидающих запросов.
Для задач требующих использования коллективных операций, используют соответствующую коллективную функцию MPI.
4 Входные и выходные данные
4.1 Этапы создания программ
Создание параллельной программы состоит из следующих этапов:
-
последовательный алгоритм подвергается декомпозиции (распараллеливанию), т.е. разбивается на независимо работающие ветви; для взаимодействия в ветви вводятся две дополнительные нематематические операции: прием и передача данных;
-
распараллеленный алгоритм записывается в виде программы, в которой операции приема и передачи записываются в терминах конкретной системы связи между ветвями;
-
полученная таким образом программа компилируется и компонуется с библиотеками среды параллельного программирования при помощи компилятора, используемого на данной системе для получения машинно-зависимого кода.
4.2 Компиляция модулей
Для компиляции и сборки программного модуля, написанного на С, используется команда mpicc. Аналогично для С++ используется команда mpiCC, для Fortran 77 используется mpif77, а для Fortran 90 – mpif90. Все команды пакета MPICH for GM настроены на использование компиляторов фирмы Compaq.
Эти команды предусматривают некоторые опции и подключают специальные библиотеки, необходимые для компиляции и сборки программ MPI:
-
опция -с указывается для выполнения только компиляции файла, не создавая объектный файл;
-
при задании опции -о осуществляется сборка и компиляция, а также создается объектный и запускаемый файлы.
Примеры
1 Компиляция программного модуля myprog.c
mpicc –c myprog.c
2 Сборка и компиляция программного модуля myprog.c с созданием выходного файла myfile
mpicc myprog.c –o myfile
4.3 Запуск программ, использующих MPI
Запуск на исполнение MPI-программы производится с помощью команды:
mpirun –np [-h –maxtime –quantum -stdiodir] [параметры_программы…]
Параметры команды mpirun слелующие:
-
параметр -h используется для выдачи интерактивной подсказки по параметрам команды mpirun;
-
параметр -np обозначает число процессоров, требуемое программе;
-
параметр -maxtime задает максимальное время счета. От этого времени зависит положение задачи в очереди. После истечения этого времени задача принудительно заканчивается;
-
параметр -quantum указывает, что задача является фоновой, и задает размер кванта для фоновой задачи;
-
параметр -stdiodir задает имя каталога стандартного вывода, в который будут записываться протокол запуска задачи, файл стандартного вывода и имена модулей, на которых запускалась задача.
Более подробное описание параметров команды запуска задач и постановки задачи в очередь приведено в руководстве “Подсистема коллективного доступа к ресурсам СК” [7].
5 Средства отладки и профилирования
В общем случае отладка параллельных программ является достаточно сложной задачей и требует специальных инструментальных средств. В пакет mpich встроены некоторые дополнительные средства, которые могут использоваться при отладке и профилировании программ MPI.
5.1 Обработчики ошибок
Стандарт MPI определяет механизм для установки пользовательских обработчиков ошибок и определяет поведение двух встроенных обработчиков: MPI_ERRORS_RETURN и MPI_ERRORS_ARE_FATAL. В библиотеку mpe встроено еще два обработчика ошибок для облегчения использования отладчика dbx с программами, написанными с использованием стандарта MPI:
MPE_Errors_call_dbx_in_xterm
MPE_Signals_call_debugger
Данные обработчики ошибок расположены в директории mpe, основного дерева каталогов MPICH. При конфигурировании MPICH с опцией -mpedbg, эти отладчики включаются в основные библиотеки MPICH, и появляется возможность (с помощью аргумента командной строки mpedbg) установить обработчик MPE_Errors_call_dbx_in_xterm вызываемым по умолчанию обработчиком ошибок (вместо MPI_ERRORS_ARE_FATAL). В приложении А приведен пример программы, обрабатывающей ошибки с помощью процедур MPI (tester.c).
5.2 Профилировочные библиотеки
Профилировочный интерфейс MPE (Message Passing Extensions) представляет собой инструмент для добавления процедур анализа производительности в любую MPI-программу. С пакетом MPICH поставляется три профилировочные библиотеки:
-
библиотека определения времени выполнения процедур MPI;
-
библиотека создания файла журнала и утилита UpShot;
-
библиотека анимации процесса работы программы в реальном времени.
В Приложении А приведен пример программы с использованием профилировочных библиотек cpilog.c.
5.2.1 Библиотека определения времени выполнения процедур MPI
Данная библиотека достаточно проста. Профилировочная версия каждой процедуры MPI (MPI_Xxx) вызывает функцию PMPI_Wtime (возвращающую текущее время) перед и после каждого вызова соответствующей PMPI_Xxx процедуры. Времена накапливаются для каждого процесса и выводятся в файл (отдельный файл для каждого процесса) в профилировочной версии MPI_Finalize. В дальнейшем эти файлы можно использовать для создания отчета по всему приложению или по отдельным процессам. Текущая реализация библиотеки не обрабатывает вложенные циклы.
5.2.2 Создание файла журнала и утилита UpShot
Эта профилировочная библиотека предназначена для генерации файла журнала (log-файла), в котором фиксируются события, привязанные ко времени.
Для сохранения определенных типов событий в памяти, в процессе выполнения вызывается процедура MPI_Log_event, а сборка и объединение этих частей памяти с информацией о событиях происходит в MPI_Finalize. Для остановки и перезапуска операций записи событий во время выполнения программы может использоваться процедура MPI_Pcontrol.
Анализ файла журнала может быть осуществлен при помощи разнообразных программных средств. Используемый для этой цели в MPICH инструмент, называется UpShot. Состояния процессов в UpShot показаны с помощью параллельных осей времени для каждого процесса. Окно внизу экрана показывает гистограмму продолжительностей процессов с несколькими корректируемыми параметрами. Вид файла журнала, полученного с помощью утилиты UpShot, представлен на рисунке 1.
Рисунок 1 – Вид файла журнала
5.2.3 Анимация процесса работы программы в реальном времени
Графическая библиотека MPE предоставляет возможности для простой анимации в реальном времени. Библиотека содержит процедуры, которые позволяют разделять X-дисплей нескольким процессам. На основе данной библиотеки существует возможность графически изображать процесс передачи сообщений и их интенсивность в процессе работы программы.
Для сборки программы с использованием графических библиотек MPE при компиляции можно указать опцию –lmpe.
В MPICH предусмотрены также опции для компиляции и сборки программ с различными профилировочными библиотеками MPE:
-mpitrace
Для компиляции и сборки с отладочными библиотеками.
-mpianim
Для компиляции и сборки с анимационными библиотеками.
-mpilog
Для компиляции и сборки с регистрирующими библиотеками .
Пример
mpif77 -mpilog -o fpilog fpilog.f
Более подробную информацию об использовании профилировочных библиотек и о синтаксисе процедур MPE можно найти в документации по МРЕ [3, 1] а также в страницах справочного руководства (man pages).
Для использования отладчиков и профилировочных библиотек необходимо указывать специальные опции при конфигурации пакета MPICH, которые можно найти в п. 3.5 Руководства системного программиста по ОПО СК “МВС-1000М” [8].
5.3 Аргументы командной строки для mpirun
Команда mpirun предоставляет программисту некоторые возможности для облегчения использования отладчика со своей программой.
Команда
mpirun -dbx -np 2 program
начинает выполнение программы на двух машинах, запуская локальную копию программы в отладчике dbx. Опция -gdb позволяет использовать в качестве gdb отладчика, а опция -xxgdb запускает программу в Х Window интерфейсе для gdb – xxgbd.
5.4 Аргументы MPI для программ пользователя
Приведенные ниже аргументы являются недокументированными возможностями MPICH. Некоторые из приведенных аргументов требуют, чтобы MPICH был сконфигурирован и собран со специальными параметрами:
—mpedbg
при возникновении ошибки в программе пользователя, запускает xterm, присоединенный к процессу, вызвавшему ошибку. MPICH должен быть сконфигурирован с опцией -mpedbg. Данный аргумент работает не на всех системах;
—mpiversion
печатает версию MPICH и аргументы, использованные при его конфигурировании;
-mpichdebug
генерирует детальную информацию по каждой производимой MPICH операции;
-mpiqueue
описывает состояние очередей вызова MPI_Finalize. Может быть использован для поиска “потерянных” сообщений.
Данные аргументы указываются программе пользователя, а не команде mpirun. Например,
mpirun -np 2 a.out -mpichdebug
Приложение A
(справочное)
Примеры программ с использованием функций MPI
В данном приложении приведены фрагменты MPI-программ (схематичные примеры) и ряд примеров прикладных программ, использующих MPI.
Перечень прикладных программ представлен в Таблице 2.
Таблица 2
имя файла |
язык |
комментарий |
параметр -np |
fpi.f |
Fortran 77 |
Вычисляет число pi, интегрируя f (x) =4 / (1+x2). |
np>=1 |
ctest.c |
C |
Пример измерения латентности для вызовов процедур MPI. |
np=2 |
cart.c |
C |
Тест виртуальной топологии |
np>1 |
tester.c |
C |
Тест обработки ошибок |
np>=1 |
srtest.c |
C |
Тест пересылки сообщений |
np>1 |
ping_pong.f |
Fortran 77 |
Измеряет время передачи сообщений между двумя процессами |
np=2 |
mpitest.c |
C |
Тест эффективности основных операций MPI |
np>=4 |
cpilog.c |
C |
Программа с использованием профилировочных библиотек |
np>2 |
А1 Схематичные примеры MPI-программ
А1.1 Схематичный пример инициализации параллельной части программы, определение кол-ва процессов в группе MPI_COMM_WORLD, где каждый процесс печатает размер группы и свой номер.
main(int argc, char **argv)
{
int me, size;
. . .
MPI_Init (&argc, &argv);
MPI_Comm_rank (MPI_COMM_WORLD, &me);
MPI_Comm_size (MPI_COMM_WORLD, &size);
(void)printf («Process %d size %dn», me, size);
. . .
MPI_Finalize();
}
А1.2 Схематичный пример программы, где главный процесс рассылает сообщения остальным процессам, а рабочие процессы группы принимают данные и выводят сообщение об этом.
#include «mpi.h»
main (argc, argv)
int argc;
char **argv;
{
char message[20];
int myrank;
MPI_Status status;
MPI_Init (&argc, &argv);
MPI_Comm_rank (MPI_COMM_WORLD, &myrank);
if (myrank==0) /* код для процесса 0*/
{
strcpy (message, «Hello, there»);
MPI_Send(messege, strlen(messege), MPI_CAHR, 1, 99, MPI_COMM_WORLD);
}
else /* код для процесса 1 */
{
MPI_Recv (message, 20, MPI_CHAR, 0, 99, MPI_COMM_WORLD, &status);
printf («receiveds :%s:n», message);
}
MPI_Finalize();
}
А1.3 Схематичный пример программы, демонстрирующий обмен сообщениями между процессами группы с помощью процедур MPI_Send и MPI_Recv
main(int argc, char **argv)
{
int me, size;
int SOME_TAG=0;
MPI_Status status;
. . .
MPI_Init (&argc, &argv);
MPI_Comm_rank (MPI_COMM_WORLD, &me); /* local */
MPI_Comm-size (MPI_COMM_WORLD, &size); /* local */
if (me % 2)==0)
{
/* Посылает процессам, пока не дойдет до последнего */
if ((me+1) < size)
MPI_Send (…, me+1, SOME_TAG, MPI_COMM_WORLD);
}
else
MPI_Recv (…, me-1, SOME_TAG, MPI_COMM_WORLD, &status);
. . .
MPI_Finalize();
}
А2 Тест виртуальных топологий (cart.c)
Это программа на С, генерирующая виртуальную топологию. При компиляции этого примера необходимо подключить (указать путь) файл test.h, который входит в стандартные примеры MPICH и находится в директории /common/mpich/examples/test/topol
#include «mpi.h»
#include
#include «test.h»
#define NUM_DIMS 2
int main( int argc, char **argv )
{
int rank, size, i;
int errors=0;
int dims[NUM_DIMS];
int periods[NUM_DIMS];
int coords[NUM_DIMS];
int new_coords[NUM_DIMS];
int reorder = 1;
MPI_Comm comm_temp, comm_cart, new_comm;
int topo_status;
int ndims;
int new_rank;
int remain_dims[NUM_DIMS];
int newnewrank;
MPI_Init( &argc, &argv );
MPI_Comm_rank( MPI_COMM_WORLD, &rank );
MPI_Comm_size( MPI_COMM_WORLD, &size );
/* Обнуление массива сетки и создание топологии */
for(i=0;i
MPI_Dims_create ( size, NUM_DIMS, dims );
/* Создание нового коммуникатора для топологии */
MPI_Cart_create ( MPI_COMM_WORLD, 2, dims, periods, reorder, &comm_temp );
MPI_Comm_dup ( comm_temp, &comm_cart );
/* Определение состояния нового коммуникатора */
MPI_Topo_test ( comm_cart, &topo_status );
if (topo_status != MPI_CART) errors++;
/* Определение кол-ва измерений сетки в топологии */
MPI_Cartdim_get( comm_cart, &ndims );
if ( ndims != NUM_DIMS ) errors++;
/* Проверка корректности полученной топологии */
for(i=0;i
MPI_Cart_get ( comm_cart, NUM_DIMS, dims, periods, coords );
/* Проверка соответствия координат процесса в сетке топологии номеру процесса */
MPI_Cart_rank ( comm_cart, coords, &new_rank );
if ( new_rank != rank ) errors++;
/* Проверка соответствия номера процесса координатам процесса в сетке топологии */
MPI_Cart_coords ( comm_cart, rank, NUM_DIMS, new_coords );
for (i=0;i
if ( coords[i] != new_coords[i] )
errors++;
/* Сдвиг в каждом измерении сетки топологии и проверка ее работы*/
for (i=0;i
int source, dest;
MPI_Cart_shift(comm_cart, i, 1, &source, &dest);
#ifdef VERBOSE
printf («[%d] Shifting %d in the %d dimensionn»,rank,1,i);
printf («[%d] source = %d dest = %dn»,rank,source,dest);
#endif
}
/* Выделение подгрупп коммуникатора для подсеток топологии */
remain_dims[0] = 0;
for (i=1; i
MPI_Cart_sub ( comm_cart, remain_dims, &new_comm );
/* Определение статуса нового коммуникатора */
MPI_Topo_test ( new_comm, &topo_status );
if (topo_status != MPI_CART) errors++;
/* Определение кол-ва измерений сетки в топологии */
MPI_Cartdim_get( new_comm, &ndims );
if ( ndims != NUM_DIMS-1 ) errors++;
/* Проверка корректности полученной топологии */
for(i=0;i
MPI_Cart_get ( new_comm, ndims, dims, periods, coords );
/* Проверка соответствия координат процесса в сетке топологии номеру процесса */
MPI_Comm_rank ( new_comm, &newnewrank );
MPI_Cart_rank ( new_comm, coords, &new_rank );
if ( new_rank != newnewrank ) errors++;
/* Проверка соответствия номера процесса координатам процесса в сетке топологии */
MPI_Cart_coords ( new_comm, new_rank, NUM_DIMS -1, new_coords );
for (i=0;i
if ( coords[i] != new_coords[i] )
errors++;
/* Завершение программы */
MPI_Comm_free( &new_comm );
MPI_Comm_free( &comm_temp );
MPI_Comm_free( &comm_cart );
Test_Waitforall( );
if (errors) printf( «[%d] done with %d ERRORS!n», rank,errors );
MPI_Finalize();
return 0;
}
Вывод результата работы программы для np=2
call_batch: calling batch
All processes completed test
Вывод результата работы программы для np=32
call_batch: calling batch
All processes completed test
А3 Тест пересылки сообщений (srtest.c)
Эта программа выдает сообщения о коммуникациях в группе.
#include «mpi.h»
#include
#define BUFLEN 512
int main(argc,argv)
int argc;
char *argv[];
{
int i, myid, numprocs, next, rc, namelen;
char buffer[BUFLEN], processor_name[MPI_MAX_PROCESSOR_NAME];
MPI_Status status;
MPI_Init(&argc,&argv);
MPI_Comm_size(MPI_COMM_WORLD,&numprocs);
MPI_Comm_rank(MPI_COMM_WORLD,&myid);
MPI_Get_processor_name(processor_name,&namelen);
fprintf(stderr,»Process %d on %sn», myid, processor_name);
strcpy(buffer,»hello there»);
if (myid == numprocs-1)
next = 0;
else
next = myid+1;
if (myid == 0)
{
printf(«%d sending ‘%s’ n»,myid,buffer);
MPI_Send(buffer, strlen(buffer)+1, MPI_CHAR, next, 99, MPI_COMM_WORLD);
printf(«%d receiving n»,myid);
MPI_Recv(buffer, BUFLEN, MPI_CHAR, MPI_ANY_SOURCE, 99, MPI_COMM_WORLD,
&status);
printf(«%d received ‘%s’ n»,myid,buffer);
}
else
{
printf(«%d receiving n»,myid);
MPI_Recv(buffer, BUFLEN, MPI_CHAR, MPI_ANY_SOURCE, 99, MPI_COMM_WORLD,
&status);
printf(«%d received ‘%s’ n»,myid,buffer);
MPI_Send(buffer, strlen(buffer)+1, MPI_CHAR, next, 99, MPI_COMM_WORLD);
printf(«%d sent ‘%s’ n»,myid,buffer);
}
MPI_Barrier(MPI_COMM_WORLD);
MPI_Finalize();
}
Вывод результата работы программы для np=2
call_batch: calling batch
1 receiving
0 sending ‘hello there’
0 receiving
0 received ‘hello there’
1 received ‘hello there’
1 sent ‘hello there’
Вывод результата работы программы для np=32
call_batch: calling batch
20 receiving
30 receiving
8 receiving
13 receiving
10 receiving
16 receiving
2 receiving
4 receiving
6 receiving
9 receiving
7 receiving
12 receiving
3 receiving
14 receiving
21 receiving
11 receiving
17 receiving
18 receiving
19 receiving
5 receiving
15 receiving
24 receiving
22 receiving
26 receiving
23 receiving
28 receiving
27 receiving
25 receiving
29 receiving
31 receiving
1 receiving
0 sending ‘hello there’
20 received ‘hello there’
20 sent ‘hello there’
30 received ‘hello there’
30 sent ‘hello there’
8 received ‘hello there’
8 sent ‘hello there’
18 received ‘hello there’
18 sent ‘hello there’
13 received ‘hello there’
13 sent ‘hello there’
10 received ‘hello there’
10 sent ‘hello there’
21 received ‘hello there’
21 sent ‘hello there’
16 received ‘hello there’
16 sent ‘hello there’
4 received ‘hello there’
4 sent ‘hello there’
2 received ‘hello there’
2 sent ‘hello there’
6 received ‘hello there’
6 sent ‘hello there’
12 received ‘hello there’
12 sent ‘hello there’
11 received ‘hello there’
11 sent ‘hello there’
9 received ‘hello there’
9 sent ‘hello there’
14 received ‘hello there’
14 sent ‘hello there’
19 received ‘hello there’
19 sent ‘hello there’
22 received ‘hello there’
22 sent ‘hello there’
28 received ‘hello there’
28 sent ‘hello there’
25 received ‘hello there’
25 sent ‘hello there’
27 received ‘hello there’
27 sent ‘hello there’
31 received ‘hello there’
31 sent ‘hello there’
3 received ‘hello there’
3 sent ‘hello there’
7 received ‘hello there’
7 sent ‘hello there’
17 received ‘hello there’
17 sent ‘hello there’
26 received ‘hello there’
26 sent ‘hello there’
23 received ‘hello there’
23 sent ‘hello there’
24 received ‘hello there’
24 sent ‘hello there’
29 received ‘hello there’
29 sent ‘hello there’
5 received ‘hello there’
5 sent ‘hello there’
15 received ‘hello there’
15 sent ‘hello there’
0 receiving
0 received ‘hello there’
1 received ‘hello there’
1 sent ‘hello there’
А4 Вычисление числа Pi ( fpi.f )
Это пример программы на Fortran 77, который вычисляет число pi интегрируя f(x) = 4/(1 + x2).
Каждый процесс:
-
получает число интервалов, используемых в приближении;
-
вычисляет в них интегралы;
-
синхронизирует для общего суммирования.
Программа выдает результат вычислений, погрешность и время вычисления.
program main
include ‘mpif.h’
double precision PI25DT
parameter (PI25DT = 3.141592653589793238462643d0)
double precision mypi, pi, h, sum, x, f, a
integer n, myid, numprocs, i, rc
c Интегрируемая функция
f(a) = 4.d0 / (1.d0 + a*a)
call MPI_INIT( ierr )
call MPI_COMM_RANK( MPI_COMM_WORLD, myid, ierr )
call MPI_COMM_SIZE( MPI_COMM_WORLD, numprocs, ierr )
print *, «Process «, myid, » of «, numprocs, » is alive»
sizetype = 1
sumtype = 2
n = 0
10 if ( myid .eq. 0 ) then
write(6,98)
98 format(‘Enter the number of intervals: (0 quits)’)
read(5,99) n
99 format(i10)
c if ( n .eq. 0 ) then
c n = 100
c else
c n = 0
c endif
print *, «got input n =», n
endif
call MPI_BCAST(n,1,MPI_INTEGER,0,MPI_COMM_WORLD,ierr)
c проверка принятия сообщения
if ( n .le. 0 ) goto 30
c вычисление размера интервала
h = 1.0d0/n
sum = 0.0d0
do 20 i = myid+1, n, numprocs
x = h * (dble(i) — 0.5d0)
sum = sum + f(x)
20 continue
mypi = h * sum
c прием всех частичных сумм
call MPI_REDUCE(mypi,pi,1,MPI_DOUBLE_PRECISION,MPI_SUM,0,
$ MPI_COMM_WORLD,ierr)
c печать ответа в 0-й ветви.
if (myid .eq. 0) then
write(6, 97) pi, abs(pi — PI25DT)
97 format(‘ pi is approximately: ‘, F18.16,
+ ‘ Error is: ‘, F18.16)
endif
goto 10
30 call MPI_FINALIZE(rc)
stop
end
Вывод результата работы программы для np=2
call_batch: calling batch
Process 1 of 2 is alive
Process 0 of 2 is alive
Enter the number of intervals: (0 quits)
Вывод результата работы программы для np=32
call_batch: calling batch
Process 29 of 32 is alive
Process 5 of 32 is alive
Process 2 of 32 is alive
Process 11 of 32 is alive
Process 4 of 32 is alive
Process 3 of 32 is alive
Process 6 of 32 is alive
Process 7 of 32 is alive
Process 8 of 32 is alive
Process 13 of 32 is alive
Process 9 of 32 is alive
Process 10 of 32 is alive
Process 12 of 32 is alive
Process 15 of 32 is alive
Process 14 of 32 is alive
Process 16 of 32 is alive
Process 19 of 32 is alive
Process 17 of 32 is alive
Process 18 of 32 is alive
Process 20 of 32 is alive
Process 21 of 32 is alive
Process 22 of 32 is alive
Process 23 of 32 is alive
Process 24 of 32 is alive
Process 26 of 32 is alive
Process 25 of 32 is alive
Process 27 of 32 is alive
Process 28 of 32 is alive
Process 30 of 32 is alive
Process 31 of 32 is alive
Process 1 of 32 is alive
Process 0 of 32 is alive
Enter the number of intervals: (0 quits)
A5 Измерение латентности вызовов процедур MPI (ctest.c)
Это пример программы на C , где латентность вызовов процедур MPI находится путем измерения разницы между временем вызова процедуры и результатами времени в эталонном тесте Dongarra.
#include «mpi.h»
#include
#include
#define MAX_TIMES 16386
static double times[MAX_TIMES];
int main( argc, argv )
int argc;
char **argv;
{
int i;
int ntest = MAX_TIMES;
double minsep, maxsep, avesep, sep, sd, deltasep, mult;
int citoutput = 1, nmatch;
MPI_Init( &argc, &argv );
/* Установление счетчиков времени */
for (i=0; i
times[i] = MPI_Wtime();
/* Получение начальных данных. При этом не измеряется время неудачных обращений к кэшу команды, занимающее дополнительное время */
for (i=0; i
times[i] = MPI_Wtime();
/* Просмотр вариантов */
minsep = 1.0e6;
maxsep = 0.0;
avesep = 0.0;
for (i=1; i
sep = times[i] — times[i-1];
if (sep < minsep) minsep = sep;
if (sep > maxsep) maxsep = sep;
avesep += sep;
}
avesep /= (ntest-1);
/* C Вычисление среднеквадратичного отклонение разниц относительно устойчивым способом */
sd = 0.0;
for (i=1; i
sep = times[i] — times[i-1];
sd += (sep — avesep) * (sep — avesep);
}
/* Масштаб в мкс */
sd *= 1.0e+12;
sd = sqrt(sd) / (ntest — 2);
/* Интересный вопрос — — все ли (или большинство) разниц являются множителями minsep. Сначала находят deltasep (время между первым и вторым различными измерениями.
*/
deltasep = maxsep;
for (i=1; i
sep = times[i] — times[i-1];
if (sep > minsep && sep < deltasep) deltasep = sep;
}
deltasep -= minsep;
/* Далее находят кол-во разниц, являющихся множителями deltasep */
nmatch = 0;
for (i=1; i
sep = times[i] — times[i-1];
mult = (sep — minsep) / deltasep;
if (fabs( mult — (int)mult) < 0.05) nmatch++;
}
/* Печать результатов */
printf( «#Variance in clock:n
#Minimum time between calls: %6.2f usecn
#Maximum time between calls: %6.2f usecn
#Average time between calls: %6.2f usecn
#Standard deviation: %12.3en»,
minsep * 1.e6, maxsep * 1.e6, avesep * 1.e6, sd );
if (nmatch > ntest/4) {
printf( «#Apparent resolution of clock is: %6.2f usecn»,
deltasep * 1.0e6 );
}
printf(
«# This program should be run multiple times for better understandingn» );
/* Print C.It graphics stuff if requested */
if (citoutput) {
for (i=1; i
sep = times[i] — times[i-1];
printf( «%fn», sep * 1.0e6 );
}
printf( «histnwaitnnew pagen» );
}
MPI_Finalize();
return 0;
}
Вывод результата работы программы для np=2
call_batch: calling batch
#Variance in clock:
#Variance in clock:
#Minimum time between calls: 0.00 usec
#Maximum time between calls: 978.11 usec
#Average time between calls: 1.37 usec
#Standard deviation: 2.856e-01
#Apparent resolution of clock is: 0.95 usec
# This program should be run multiple times for better understanding
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
…………………
975.966454
2.026558
…………………
0.000000
0.000000
…………………
Вывод результата работы программы для np=32
call_batch: calling batch
#Variance in clock:
#Minimum time between calls: 0.00 usec
#Maximum time between calls: 977.99 usec
#Average time between calls: 0.84 usec
#Standard deviation: 2.230e-01
#Apparent resolution of clock is: 0.95 usec
# This program should be run multiple times for better understanding
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
…………………
0.000000
#Minimum time between calls: 0.00 usec
#Maximum time between calls: 978.11 usec
#Average time between calls: 1.01 usec
#Standard deviation: 2.457e-01
#Apparent resolution of clock is: 0.95 usec
# This program should be run multiple times for better understanding
0.000000
0.000000
0.000000
…………………
A6 Тест обработки ошибок (testerr.c)
Эта программа показывает работу процедур для обработки ошибок.
#include
#include
void Test_Send( void );
void Test_Recv( void );
void Test_Datatype( void );
void Test_Errors_warn( MPI_Comm *comm, int *code, … )
{
char buf[MPI_MAX_ERROR_STRING+1];
int myid, result_len;
static int in_handler = 0;
if (in_handler) return;
in_handler = 1;
/* Преобразование кода ошибки в сообщение и печать */
MPI_Error_string( *code, buf, &result_len );
printf( «%sn», buf );
in_handler = 0;
}
static int errcount = 0;
void Test_Failed( char * msg )
{
printf( «FAILED: %sn», msg );
errcount++;
}
void Test_Passed( char * msg )
{
printf( «Passed: %sn», msg );
}
int main( int argc, char *argv[] )
{
MPI_Errhandler TEST_ERRORS_WARN;
MPI_Init( &argc, &argv );
MPI_Errhandler_create( Test_Errors_warn, &TEST_ERRORS_WARN );
MPI_Errhandler_set(MPI_COMM_WORLD, TEST_ERRORS_WARN);
Test_Send();
Test_Recv();
Test_Datatype();
MPI_Finalize();
return 0;
}
void Test_Send( void )
{
int buffer[100];
int dest;
MPI_Datatype bogus_type = MPI_DATATYPE_NULL;
MPI_Status status;
int myrank, size;
int large_tag, flag, small_tag;
int *tag_ubp;
MPI_Comm_rank( MPI_COMM_WORLD, &myrank );
MPI_Comm_size( MPI_COMM_WORLD, &size );
dest = size — 1;
if (MPI_Send(buffer, 20, MPI_INT, dest,
1, MPI_COMM_NULL) == MPI_SUCCESS){
Test_Failed(«NULL Communicator Test»);
}
else
Test_Passed(«NULL Communicator Test»);
if (MPI_Send(buffer, -1, MPI_INT, dest,
1, MPI_COMM_WORLD) == MPI_SUCCESS){
Test_Failed(«Invalid Count Test»);
}
else
Test_Passed(«Invalid Count Test»);
if (MPI_Send(buffer, 20, bogus_type, dest,
1, MPI_COMM_WORLD) == MPI_SUCCESS){
Test_Failed(«Invalid Type Test»);
}
else
Test_Passed(«Invalid Type Test»);
small_tag = -1;
if (small_tag == MPI_ANY_TAG) small_tag = -2;
if (MPI_Send(buffer, 20, MPI_INT, dest,
small_tag, MPI_COMM_WORLD) == MPI_SUCCESS) {
Test_Failed(«Invalid Tag Test»);
}
else
Test_Passed(«Invalid Tag Test»);
/* Тег сообщения слишком велик */
MPI_Attr_get( MPI_COMM_WORLD, MPI_TAG_UB, (void **)&tag_ubp, &flag );
if (!flag) Test_Failed(«Could not get tag ub!» );
large_tag = *tag_ubp + 1;
if (large_tag > *tag_ubp) {
if (MPI_Send(buffer, 20, MPI_INT, dest,
-1, MPI_COMM_WORLD) == MPI_SUCCESS) {
Test_Failed(«Invalid Tag Test»);
}
else
Test_Passed(«Invalid Tag Test»);
}
if (MPI_Send(buffer, 20, MPI_INT, 300,
1, MPI_COMM_WORLD) == MPI_SUCCESS) {
Test_Failed(«Invalid Destination Test»);
}
else
Test_Passed(«Invalid Destination Test»);
if (MPI_Send((void *)0, 10, MPI_INT, dest,
1, MPI_COMM_WORLD) == MPI_SUCCESS){
Test_Failed(«Invalid Buffer Test (send)»);
}
else
Test_Passed(«Invalid Buffer Test (send)»);
}
void Test_Recv( void )
{
}
void Test_Datatype( void )
{
}
#ifdef FOO
void
ReceiverTest3()
{
int buffer[20];
MPI_Datatype bogus_type = MPI_DATATYPE_NULL;
MPI_Status status;
int myrank;
int *tag_ubp;
int large_tag, flag, small_tag;
MPI_Comm_rank( MPI_COMM_WORLD, &myrank );
if (myrank == 0) {
fprintf( stderr,
«There should be eight error messages about invalid communicatorn
count argument, datatype argument, tag, rank, buffer send and buffer recvn» );
}
/* Тест посылки сообщений может не выдавать ошибок, пока он не запущен */
if (MPI_Recv((void *)0, 10, MPI_INT, src,
15, MPI_COMM_WORLD, &status) == MPI_SUCCESS){
Test_Failed(«Invalid Buffer Test (recv)»);
}
else
Test_Passed(«Invalid Buffer Test (recv)»);
/* Прием посылаеммого сообщения */
{ int flag, ibuf[10];
MPI_Iprobe( src, 15, MPI_COMM_WORLD, &flag, &status );
if (flag)
MPI_Recv( ibuf, 10, MPI_INT, src, 15, MPI_COMM_WORLD, &status );
}
return;
#endif
Вывод результата работы программы для np=2
call_batch: calling batch
Null communicator
Null communicator
Passed: NULL Communicator Test
Invalid count argument is -1
Passed: Invalid Count Test
Datatype is MPI_TYPE_NULL
Passed: Invalid Type Test
Invalid message tag -2
Passed: Invalid Tag Test
Invalid message tag -1
Passed: Invalid Tag Test
Invalid rank 300
Passed: Invalid Destination Test
Invalid buffer pointer
Passed: Invalid Buffer Test (send)
Passed: NULL Communicator Test
Invalid count argument is -1
Passed: Invalid Count Test
Datatype is MPI_TYPE_NULL
Passed: Invalid Type Test
Invalid message tag -2
Passed: Invalid Tag Test
Вывод результата работы программы для np=32
call_batch: calling batch
Null communicator
Null communicator
Null communicator
Null communicator
Null communicator
Null communicator
Null communicator
Null communicator
Null communicator
Null communicator
Null communicator
Null communicator
Null communicator
Null communicator
Passed: NULL Communicator Test
Invalid count argument is -1
Passed: Invalid Count Test
Datatype is MPI_TYPE_NULL
Passed: Invalid Type Test
Invalid message tag -2
Passed: Invalid Tag Test
Invalid message tag –1
Passed: Invalid Tag Test
Invalid rank 300
Passed: Invalid Destination Test
Invalid buffer pointer
Passed: Invalid Buffer Test (send)
Null communicator
Passed: NULL Communicator Test
Invalid count argument is -1
Passed: Invalid Count Test
Datatype is MPI_TYPE_NULL
Passed: Invalid Type Test
Invalid message tag -2
Passed: Invalid Tag Test
Invalid message tag -1
Passed: Invalid Tag Test
Invalid rank 300
Passed: Invalid Destination Test
Invalid buffer pointer
……………………………………………………
A7 Обмен сообщениями (ping_pong.f)
Этот пример измеряет скорость пересылки сообщений.
PROGRAM PingPong
INCLUDE ‘mpif.h’
integer p
integer my_rank
integer test
integer min_size
integer max_size
integer incr
integer size
parameter (min_size = 0, max_size = 10000, incr = 200)
parameter (size = 80000)
double precision x(0:size)
integer pass
integer status(MPI_STATUS_SIZE)
integer ierr
integer i
double precision wtime_overhead
double precision start, finish,timex
double precision raw_time, cumulativ,y,tmin
double precision dtime(0:127,0:127),delta,tmax,tavg
double precision tmax2,tmin2,tavg2
integer comm, count(0:127)
integer MAX_ORDER, MAX
parameter (MAX_ORDER = 1000, MAX =
character*23 nodes(0:127),dummy
character*4 pname(0:127), myname
C
call MPI_INIT( ierr)
call MPI_COMM_SIZE(MPI_COMM_WORLD, p, ierr )
call MPI_COMM_RANK(MPI_COMM_WORLD, my_rank, ierr )
call MPI_COMM_DUP(MPI_COMM_WORLD, comm, ierr )
call MPI_GET_PROCESSOR_NAME(myname,len,ierr)
call MPI_GATHER(myname,4,MPI_CHARACTER,pname,4,
+ MPI_CHARACTER,0,MPI_COMM_WORLD,ierr)
call MPI_BCAST(pname,512,MPI_CHARACTER,0,MPI_COMM_WORLD,ierr)
if(my_rank.eq.0) print*,»Starting…»
C
C
y=4.D0*DATAN(1.D0)
do 9 i=1,size
x(i)=y
9 continue
noff=mod(p,2)
C mynoff=mod(myrank,2)
if(noff.eq.1) then
print*, «Error: odd number of processes…»
stop
endif
print 181, my_rank
tavg=0.D0
tmin=99.D99
tmax=0.D0
delta=3.0D-004
C nloops=20
nloops=200
mynoff=mod(my_rank,2)
do 101 nnn=0,1
do 100 i=1,p-1,2
ndest=my_rank+i
nsend=my_rank-i
if(ndest.ge.p) ndest=mod(ndest,p)
if(nsend.lt.0) nsend=nsend+p
call MPI_BARRIER(comm, ierr)
if (mynoff.eq.nnn) then
timex=0.D0
do 20 k=1,nloops
start = MPI_WTIME()
call MPI_SEND(x, size,MPI_DOUBLE_PRECISION,
+ ndest,0,comm,ierr)
finish = MPI_WTIME()
timex=timex+(finish-start)
11 continue
20 continue
ttime=timex/dble(nloops)
tavg=tavg+ttime
if(ttime.gt.tmax) tmax=ttime
if(ttime.lt.tmin) tmin=ttime
else
nflag=0
do 22 k=1,nloops
call MPI_RECV(x,size,MPI_DOUBLE_PRECISION,nsend,
+ 0,comm,status, ierr)
do 21 k1=1,size
if (DABS(x(k1)-y).gt.1D-16) then
print 179, x(k1)
print 182, nsend,comm,status,ierr
print 180, my_rank, k1, k1
print 178, y
nflag=1
endif
21 continue
22 continue
if(nflag.eq.1)print 177, pname(nsend),
+ pname(my_rank),nsend,my_rank
endif
100 continue
101 continue
call MPI_REDUCE(tmin, tmin2, 1, MPI_DOUBLE_PRECISION, MPI_MIN, 0,
+ MPI_COMM_WORLD, ierr)
call MPI_REDUCE(tmax, tmax2, 1, MPI_DOUBLE_PRECISION, MPI_MAX, 0,
+ MPI_COMM_WORLD, ierr)
call MPI_REDUCE(tavg, tavg2, 1, MPI_DOUBLE_PRECISION, MPI_SUM, 0,
+ MPI_COMM_WORLD, ierr)
if (my_rank.eq.0) then
print*,»Max time: «,tmax2
print*,»Min time: «,tmin2
print*,»Avg time: «,tavg2/dble(p**2/4)
endif
176 format(«Excessive Message Delay?: «,A,» -> «,A,2x,I3,2x,I3,
+ 2x,D17.10)
177 format(«Message Error: «,A,» -> «,A,2x,I3,2x,I3,2x,D17.10,2x,
+ D17.10)
181 format(2x,»my rank «, I5)
178 format(10x,»Sent: «,Z17)
179 format(10x,»Recv: «,Z17)
182 format(5x,»Message from»,2x,I3,3x,»comm»,2x,I4,3x,»status»,
+ 2x,Z8,3x,»ierr»,2x,I4)
180 format(12x,»my rank «,I4,3x,»index «,I8,3x,»in hex»,Z8)
call MPI_FINALIZE(ierr)
end
Вывод результата работы программы для np=2
call_batch: calling batch
Starting…
my rank 1
my rank 0
Max time: 3.239690558984876E-003
Min time: 3.174345009028912E-003
Avg time: 6.414035568013787E-003
A8 Тест эффективности основных операций MPI ( mpitest)
#include
#include
#include
#define Wtime MPI_Wtime
#define MEGABYTE (1024*1024)
#define BUFFER_SIZE 1024
#define TAG1 17
#define MASTER_RANK 0
#define MAX_REQUESTS 16
#define MILLION 1000000.0
static int NTIMES = 10000;
static int NTIMES_PREC = 100000;
#define NTIMES_TIMING NTIMES_PREC
#define NTIMES_BARRIER NTIMES_PREC
#define NTIMES_LATENCY NTIMES_PREC
#define TEST_SENDRECV 0
#define MASTER if(i_am_the_master)
int nproc,myid;
int i_am_the_master = 0;
int buf[BUFFER_SIZE],obuf[BUFFER_SIZE];
void Test_MPI_Routines(MPI_Comm comm);
int main(int argc,char *argv[]) {
int i;
double t_start,t_end;
MPI_Init(&argc,&argv);
MPI_Comm_size(MPI_COMM_WORLD,&nproc);
MPI_Comm_rank(MPI_COMM_WORLD,&myid);
i_am_the_master = (myid == MASTER_RANK);
t_start = Wtime();
MASTER printf(«MPItest/C 1.0: running %d processes…n»,nproc);
if(nproc < 4) {
MASTER printf(«MPItest expects at least 4 processesn»);
MPI_Finalize();
exit(0);
}
MASTER /* читает параметры коммандной строки */
for(i = 1; i < argc; i ++)
switch(argv[i][0]) {
case ‘T’: NTIMES = atoi(argv[i]+1); break; case ‘t’: NTIMES_PREC = atoi(argv[i]+1); break; default: fprintf(stderr,»WARNING: unrecognized option: %sn»,argv[i]);
break;
}
MPI_Bcast(&NTIMES,1,MPI_INT,MASTER_RANK,MPI_COMM_WORLD);
MPI_Bcast(&NTIMES_PREC,1,MPI_INT,MASTER_RANK,MPI_COMM_WORLD);
MASTER printf(«Testing basic MPI routines.n»);
Test_MPI_Routines(MPI_COMM_WORLD);
t_end = Wtime();
MASTER printf(«MPItest/C complete in %g sec.n»,t_end-t_start);
MPI_Finalize();
return 0;
}
void Test_MPI_Routines(MPI_Comm comm) {
int nproc,myid,i;
int i_am_the_master = 0;
double t, t1, t2, tt, dt, lat, tb;
MPI_Status status, statuses[MAX_REQUESTS];
MPI_Request request, requests[MAX_REQUESTS];
MPI_Comm_size(MPI_COMM_WORLD,&nproc);
MPI_Comm_rank(MPI_COMM_WORLD,&myid);
i_am_the_master = (myid == MASTER_RANK);
MPI_Barrier(comm);
/* Инициализация буффера */
for(i = 0; i < BUFFER_SIZE; i ++) buf[i] = myid;
/* —— Измерение времени между вызовами MPI_Wtime() —— */
MASTER printf(«** Timing for MPI operations in microseconds ***n»);
dt = 0;
MASTER for(i = 0; i < NTIMES_TIMING; i ++)
{
t1 = Wtime();
t2 = Wtime();
dt += (t2 — t1);
}
dt /= (double) NTIMES_TIMING;
t = dt;
t *= MILLION;
MASTER printf(«%gttTimingn»,t);
fflush(stdout);
/* ———— Проверка барьера синхронизации ———- */
tb = 0;
for(i = 0; i < NTIMES_BARRIER; i ++)
{
MPI_Barrier(comm);
t1 = Wtime();
MPI_Barrier(comm);
t2 = Wtime();
tb += (t2 — t1 — dt);
}
tb /= (double) NTIMES_BARRIER;
t = tb;
t *= MILLION;
MASTER printf(«%gttBarriern»,t);
fflush(stdout);
/* —— Объединение данных от всех ветвей с помощью MPI_Allreduce —— */
t = 0;
for(i = 0; i < NTIMES; i ++)
{
MPI_Barrier(comm);
t1 = Wtime();
MPI_Allreduce(buf,obuf,1,MPI_INT,MPI_SUM,comm);
MPI_Barrier(comm);
t2 = Wtime();
t += (t2 — t1 — dt — tb);
}
t /= (double) NTIMES;
t *= MILLION;
MASTER printf(«%gttGlobal sum (Allreduce)n»,t);
fflush(stdout);
/* ——-Объединение данных от всех ветвей с помощью MPI_Allreduce —— */
t = 0;
for(i = 0; i < NTIMES; i ++)
{
MPI_Barrier(comm);
t1 = Wtime();
MPI_Allreduce(buf,obuf,10,MPI_INT,MPI_SUM,comm);
MPI_Barrier(comm);
t2 = Wtime();
t += (t2 — t1 — dt — tb);
}
t /= (double) NTIMES;
t *= MILLION;
MASTER printf(«%gtt10 global sums (Allreduce)n»,t);
fflush(stdout);
/* ——-Объединение данных от всех ветвей с помощью MPI_Allreduce —— */
t = 0;
for(i = 0; i < NTIMES; i ++)
{
MPI_Barrier(comm);
t1 = Wtime();
MPI_Reduce(buf,obuf,1,MPI_INT,MPI_SUM,MASTER_RANK,comm);
t2 = Wtime();
t += (t2 — t1 — dt);
}
t /= (double) NTIMES;
t *= MILLION;
MASTER printf(«%gttGlobal sum (Reduce)n»,t);
fflush(stdout);
/* ——-Объединение данных от всех ветвей с помощью MPI_Allreduce —— */
t = 0;
for(i = 0; i < NTIMES; i ++)
{
MPI_Barrier(comm);
t1 = Wtime();
MPI_Reduce(buf,obuf,10,MPI_INT,MPI_SUM,MASTER_RANK,comm);
t2 = Wtime();
t += (t2 — t1 — dt);
}
t /= (double) NTIMES;
t *= MILLION;
MASTER printf(«%gtt10 Global sums (Reduce)n»,t);
fflush(stdout);
/*Использование процедуры передачи сообщения от главного процесса остальным*/
t = 0;
for(i = 0; i < NTIMES; i ++)
{
MPI_Barrier(comm);
t1 = Wtime();
MPI_Bcast(buf,1,MPI_INT,MASTER_RANK,comm);
MPI_Barrier(comm);
t2 = Wtime();
t += (t2 — t1 — dt — tb);
}
t /= (double) NTIMES;
t *= MILLION;
MASTER printf(«%gttBroadcastn»,t);
fflush(stdout);
/* Использование процедуры сбора сообщений главным процессом от остальных */
t = 0;
for(i = 0; i < NTIMES; i ++)
{
MPI_Barrier(comm);
t1 = Wtime();
MPI_Gather(buf,1,MPI_INT,obuf,1,MPI_INT,MASTER_RANK,comm);
MPI_Barrier(comm);
t2 = Wtime();
t += (t2 — t1 — dt — tb);
}
t /= (double) NTIMES;
t *= MILLION;
MASTER printf(«%gttGathern»,t);
fflush(stdout);
/* Использование неблокирующей посылки сообщений и ожидания ее конца MPI_Wait */
t = 0;
if(i_am_the_master)
for(i = 0; i < NTIMES; i ++)
{
t1 = Wtime();
MPI_Isend(buf,10,MPI_INT,1,TAG1,comm,&request);
MPI_Wait(&request,&status);
t2 = Wtime();
t += (t2 — t1 — dt);
}
else if(myid == 1)
for(i = 0; i < NTIMES; i ++)
{
MPI_Irecv(obuf,10,MPI_INT,MASTER_RANK,TAG1,comm,&request);
MPI_Wait(&request,&status);
}
t /= (double) NTIMES;
t *= MILLION;
MASTER printf(«%gttNon-blocking send with waitn»,t);
fflush(stdout);
/* Использование блокирующей посылки сообщений ———- */
t = 0;
if(i_am_the_master)
for(i = 0; i < NTIMES; i ++)
{
t1 = Wtime();
MPI_Send(buf,10,MPI_INT,1,TAG1,comm);
t2 = Wtime();
t += (t2 — t1 — dt);
}
else if(myid == 1)
for(i = 0; i < NTIMES; i ++)
MPI_Recv(obuf,10,MPI_INT,MASTER_RANK,TAG1,comm,&status);
t /= (double) NTIMES;
t *= MILLION;
MASTER printf(«%gttBlocking vector sendn»,t);
fflush(stdout);
/* ——— Использование одновременной передачи и приема сообщения —- */
t = 0;
if(i_am_the_master)
for(i = 0; i < NTIMES; i ++)
{
t1 = Wtime();
MPI_Sendrecv(buf,1,MPI_INT,1,TAG1,obuf,1, MPI_INT, 1, TAG1, comm,statuses);
t2 = Wtime();
t += (t2 — t1 — dt);
}
else if(myid == 1)
for(i = 0; i < NTIMES; i ++)
MPI_Sendrecv(buf, 1, MPI_INT, MASTER_RANK, TAG1,obuf, 1, MPI_INT, MASTER_RANK, TAG1, comm,statuses);
t /= (double) NTIMES;
t *= MILLION;
MASTER printf(«%gttSendRecvn»,t);
fflush(stdout);
/* — Использование последовательной передачи и приема сообщения —-*/
t = 0;
if(i_am_the_master)
for(i = 0; i < NTIMES; i ++)
{
t1 = Wtime();
MPI_Send(buf,1,MPI_INT,1,TAG1,comm);
MPI_Recv(obuf,1,MPI_INT, 1,TAG1,comm,&status);
t2 = Wtime();
t += (t2 — t1 — dt);
}
else if(myid == 1)
for(i = 0; i < NTIMES; i ++)
{
MPI_Recv(obuf,1,MPI_INT,MASTER_RANK,TAG1,comm,&status);
MPI_Send(buf,1,MPI_INT,MASTER_RANK,TAG1,comm);
}
t /= (double) NTIMES;
t *= MILLION;
MASTER printf(«%gttSend and receiven»,t);
fflush(stdout);
/* —-Одновременное выполнение запросов на посылка сообщенияs —- */
#if 1
t = 0;
if(i_am_the_master)
{
MPI_Send_init(&buf[0],1,MPI_INT,1,TAG1,comm,&requests[0]);
MPI_Send_init(&buf[1],1,MPI_INT,1,TAG1,comm,&requests[1]);
MPI_Send_init(&buf[2],1,MPI_INT,1,TAG1,comm,&requests[2]);
MPI_Send_init(&buf[3],1,MPI_INT,1,TAG1,comm,&requests[3]);
MPI_Send_init(&buf[4],1,MPI_INT,1,TAG1,comm,&requests[4]);
for(i = 0; i < NTIMES; i ++)
{
t1 = Wtime();
MPI_Startall(5,requests);
MPI_Waitall(5,requests,statuses);
t2 = Wtime();
t += (t2 — t1 — dt);
}
MPI_Request_free(&requests[0]);
MPI_Request_free(&requests[1]);
MPI_Request_free(&requests[2]);
MPI_Request_free(&requests[3]);
MPI_Request_free(&requests[4]);
}
else if(myid == 1)
{
MPI_Recv_init(&obuf[0],1,MPI_INT,0,TAG1,comm,&requests[0]);
MPI_Recv_init(&obuf[1],1,MPI_INT,0,TAG1,comm,&requests[1]);
MPI_Recv_init(&obuf[2],1,MPI_INT,0,TAG1,comm,&requests[2]);
MPI_Recv_init(&obuf[3],1,MPI_INT,0,TAG1,comm,&requests[3]);
MPI_Recv_init(&obuf[4],1,MPI_INT,0,TAG1,comm,&requests[4]);
for(i = 0; i < NTIMES; i ++)
{
MPI_Startall(5,requests);
MPI_Waitall(5,requests,statuses);
}
MPI_Request_free(&requests[0]);
MPI_Request_free(&requests[1]);
MPI_Request_free(&requests[2]);
MPI_Request_free(&requests[3]);
MPI_Request_free(&requests[4]);
}
t /= (double) NTIMES;
t *= MILLION;
MASTER printf(«%gtt5 sends in onen»,t);
fflush(stdout);
#endif
/* ———— Выполнение посылки сообщения по запросу ———- */
t = 0;
if(i_am_the_master)
for(i = 0; i < NTIMES; i ++)
{
t1 = Wtime();
MPI_Isend(&buf[0],1,MPI_INT,1,TAG1,comm, &requests[0]);
MPI_Isend(&buf[0],1,MPI_INT,1,TAG1,comm, &requests[1]);
MPI_Isend(&buf[0],1,MPI_INT,1,TAG1,comm, &requests[2]);
MPI_Isend(&buf[0],1,MPI_INT,1,TAG1,comm, &requests[3]);
MPI_Isend(&buf[0],1,MPI_INT,1,TAG1,comm, &requests[4]);
MPI_Waitall(5,requests,statuses);
t2 = Wtime();
t += (t2 — t1 — dt);
}
else if(myid == 1)
for(i = 0; i < NTIMES; i ++)
{
MPI_Irecv(&obuf[0],1,MPI_INT,MASTER_RANK,TAG1,comm, &requests[0]);
MPI_Irecv(&obuf[1],1,MPI_INT,MASTER_RANK,TAG1,comm, &requests[1]);
MPI_Irecv(&obuf[2],1,MPI_INT,MASTER_RANK,TAG1,comm, &requests[2]);
MPI_Irecv(&obuf[3],1,MPI_INT,MASTER_RANK,TAG1,comm, &requests[3]);
MPI_Irecv(&obuf[4],1,MPI_INT,MASTER_RANK,TAG1,comm, &requests[4]);
MPI_Waitall(5,requests,statuses);
}
t /= (double) NTIMES;
t *= MILLION;
MASTER printf(«%gtt5 async. sendsn»,t);
fflush(stdout);
/* ———— Проверка посылкиприема сигнала ———- */
t = 0;
if(i_am_the_master)
for(i = 0; i < NTIMES_LATENCY; i ++)
{
t1 = Wtime();
/* Was:
MPX_Sig_send(1,TAG1,comm);
MPX_Sig_wait(1,TAG1,comm);
*/
MPI_Send(NULL,0,MPI_INT,1,TAG1,comm);
MPI_Recv(NULL,0,MPI_INT,1,TAG1,comm,&status);
t2 = Wtime();
t += (t2 — t1 — dt);
}
else if(myid == 1)
for(i = 0; i < NTIMES_LATENCY; i ++)
{
MPI_Recv(NULL,0,MPI_INT,MASTER_RANK,TAG1,comm,&status);
MPI_Send(NULL,0,MPI_INT,MASTER_RANK,TAG1,comm);
}
t /= (double) NTIMES_LATENCY;
t *= MILLION;
MASTER printf(«%gttsignal sending (latency)n»,t);
fflush(stdout);
}
Вывод результата работы программы для np=5
call_batch: calling batch
MPItest/C 1.0: running 5 processes…
Testing basic MPI routines.
** Timing for MPI operations in microseconds ***
0.655001 Timing
60.8215 Barrier
48.7546 Global sum (Allreduce)
52.8754 10 global sums (Allreduce)
48.4172 Global sum (Reduce)
48.7901 10 Global sums (Reduce)
26.4905 Broadcast
8.60672 Gather
0.908893 Non-blocking send with wait
0.909001 Blocking vector send
4.42849 SendRecv
5.79681 Send and receive
7712.04 5 sends in one
Вывод результата работы программы для np=32
call_batch: calling batch
MPItest/C 1.0: running 32 processes…
Testing basic MPI routines.
** Timing for MPI operations in microseconds ***
0.614616 Timing
172.913 Barrier
143.482 Global sum (Allreduce)
152.485 10 global sums (Allreduce)
138.163 Global sum (Reduce)
116.008 10 Global sums (Reduce)
58.7728 Broadcast
17.9147 Gather
1.63228 Non-blocking send with wait
1.2411 Blocking vector send
4.4676 SendRecv
5.83727 Send and receive
A9 Пример программы с использованием профилировочных библиотек MPE ( cpilog.c)
Эта программа вычисляет число pi , и выводит информацию о времени вычисления для каждого процесса отдельно. Программа использует профилировочные библиотеки MPE. Просмотр файла регистрационного журнала cpilog.clog можно выполнить при помощи утилиты Jumpshot-2
#include «mpi.h»
#include «mpe.h»
#include
#include
double f( double );
double f( double a)
{
return (4.0 / (1.0 + a*a));
}
int main( int argc, char *argv[])
{
int n, myid, numprocs, i, j;
double PI25DT = 3.141592653589793238462643;
double mypi, pi, h, sum, x;
double startwtime = 0.0, endwtime;
int namelen;
int event1a, event1b, event2a, event2b,
event3a, event3b, event4a, event4b;
char processor_name[MPI_MAX_PROCESSOR_NAME];
MPI_Init(&argc,&argv);
MPI_Comm_size(MPI_COMM_WORLD,&numprocs);
MPI_Comm_rank(MPI_COMM_WORLD,&myid);
MPI_Get_processor_name(processor_name,&namelen);
fprintf(stderr,»Process %d running on %sn», myid, processor_name);
/*
MPE_Init_log() & MPE_Finish_log() не нуждается в библиотеке liblmpe.a. Но в случае ее прилинкования ,
MPI_Init() автоматически вызовет процедуре MPE_Init_log().
*/
/*
MPE_Init_log();
*/
/* Назначение ID номера от MPE, пользователю не надо делать это вручную */
event1a = MPE_Log_get_event_number();
event1b = MPE_Log_get_event_number();
event2a = MPE_Log_get_event_number();
event2b = MPE_Log_get_event_number();
event3a = MPE_Log_get_event_number();
event3b = MPE_Log_get_event_number();
event4a = MPE_Log_get_event_number();
event4b = MPE_Log_get_event_number();
if (myid == 0) {
MPE_Describe_state(event1a, event1b, «Broadcast», «red»);
MPE_Describe_state(event2a, event2b, «Compute», «blue»);
MPE_Describe_state(event3a, event3b, «Reduce», «green»);
MPE_Describe_state(event4a, event4b, «Sync», «orange»);
}
if (myid == 0)
{
n = 1000000;
startwtime = MPI_Wtime();
}
MPI_Barrier(MPI_COMM_WORLD);
MPE_Start_log();
for (j = 0; j < 5; j++)
{
MPE_Log_event(event1a, 0, «start broadcast»);
MPI_Bcast(&n, 1, MPI_INT, 0, MPI_COMM_WORLD);
MPE_Log_event(event1b, 0, «end broadcast»);
MPE_Log_event(event4a,0,»Start Sync»);
MPI_Barrier(MPI_COMM_WORLD);
MPE_Log_event(event4b,0,»End Sync»);
MPE_Log_event(event2a, 0, «start compute»);
h = 1.0 / (double) n;
sum = 0.0;
for (i = myid + 1; i <= n; i += numprocs)
{
x = h * ((double)i — 0.5);
sum += f(x);
}
mypi = h * sum;
MPE_Log_event(event2b, 0, «end compute»);
MPE_Log_event(event3a, 0, «start reduce»);
MPI_Reduce(&mypi, &pi, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD);
MPE_Log_event(event3b, 0, «end reduce»);
}
/*
MPE_Finish_log(«cpilog»);
*/
if (myid == 0)
{
endwtime = MPI_Wtime();
printf(«pi is approximately %.16f, Error is %.16fn»,
pi, fabs(pi — PI25DT));
printf(«wall clock time = %fn», endwtime-startwtime);
}
MPI_Finalize();
return(0);
}
Для просмотра файла регистрационного журнала в текстовом режиме можно использовать утилиту clog_print, например:
./clog_print cpilog.clog >> readfile
Для данного примера файл регистрационного журнала будет следующим:
ts=0.000000 type=loc len=9, pid=0 srcid=900 line=339 file=clog.c
ts=0.000000 type=comm len=5, pid=0 et=init pt=-1 ncomm=91 srcid=900
ts=0.000000 type=loc len=9, pid=0 srcid=901 line=284 file=clog.c
ts=0.000000 type=raw len=7, pid=0 id=-201 data=-1 srcid=901 desc=MPI_PROC_NULL
ts=0.000000 type=raw len=7, pid=0 id=-201 data=-2 srcid=901 desc=MPI_ANY_SOURCE
ts=0.000000 type=raw len=7, pid=0 id=-201 data=-1 srcid=901 desc=MPI_ANY_TAG
ts=0.001953 type=loc len=9, pid=0 srcid=902 line=364 file=clog.c
ts=0.001953 type=sdef len=10, pid=0 id=200 start=500 end=501 color=red desc=Broa
ts=0.001953 type=sdef len=10, pid=0 id=201 start=502 end=503 color=blue desc=Com
ts=0.001953 type=sdef len=10, pid=0 id=202 start=504 end=505 color=green desc=Re
ts=0.001953 type=sdef len=10, pid=0 id=203 start=506 end=507 color=orange desc=S
ts=0.001953 type=raw len=7, pid=0 id=11 data=1 srcid=901 desc=
ts=0.001953 type=raw len=7, pid=0 id=12 data=2 srcid=901 desc=
ts=0.001953 type=raw len=7, pid=0 id=500 data=0 srcid=901 desc=start broadcast
ts=0.001953 type=raw len=7, pid=0 id=13 data=1 srcid=901 desc=
ts=0.001953 type=raw len=7, pid=0 id=14 data=2 srcid=901 desc=
ts=0.001953 type=raw len=7, pid=0 id=501 data=0 srcid=901 desc=end broadcast
ts=0.001953 type=raw len=7, pid=0 id=506 data=0 srcid=901 desc=Start Sync
ts=0.001953 type=raw len=7, pid=0 id=11 data=3 srcid=901 desc=
ts=0.001953 type=raw len=7, pid=0 id=12 data=4 srcid=901 desc=
ts=0.001953 type=raw len=7, pid=0 id=507 data=0 srcid=901 desc=End Sync
ts=0.001953 type=raw len=7, pid=0 id=502 data=0 srcid=901 desc=start compute
ts=0.020508 type=raw len=7, pid=0 id=503 data=0 srcid=901 desc=end compute
ts=0.020508 type=raw len=7, pid=0 id=503 data=0 srcid=901 desc=end compute
ts=0.020508 type=raw len=7, pid=0 id=504 data=0 srcid=901 desc=start reduce
ts=0.020508 type=raw len=7, pid=0 id=25 data=1 srcid=901 desc=
ts=0.020508 type=raw len=7, pid=0 id=26 data=2 srcid=901 desc=
Hi,
I am trying to compile a simple piece of code using ifort 11 and a local installation of mpich.
This is on an IBM e1350 cluster running SuSE Linux Enterprise 9 SP3.
It is basically the ‘hello world’ for mpi.
[plain] program main include 'mpif.h' integer myrank, mysize, rc call MPI_INIT( ierr ) call MPI_COMM_SIZE(MPI_COMM_WORLD,mysize,ierr) call MPI_COMM_RANK(MPI_COMM_WORLD,myrank,ierr) print *, 'Hello World! I am ', myrank, ' of ', mysize, '.' call MPI_FINALIZE(rc) stop end [/plain]
I cannot seem to compile this using ifort, i.e.
ifort hello_mpi.f -o hello-mpi.out -I/
I get:
/tmp/ifort3DEBtP.o(.text+0x3f): In function `MAIN__’:
: undefined reference to `mpi_init_’
/tmp/ifort3DEBtP.o(.text+0x5b): In function `MAIN__’:
: undefined reference to `mpi_comm_size_’
/tmp/ifort3DEBtP.o(.text+0x77): In function `MAIN__’:
: undefined reference to `mpi_comm_rank_’
/tmp/ifort3DEBtP.o(.text+0x152): In function `MAIN__’:
: undefined reference to `mpi_finalize_’
I’ve tried many variations of adding or removing underscores etc but nothing seems to work.
The code does however compile via the pathscale compiler. And mpich is built with pathscale.
Sorry i’m new to MPI. Do I have to have an ifort version of mpich? Is there no other way?
regards,
Tanksnr.
I was trying to install and run MS-MPI following this tutorial. I have installed MS-MPI and all my system variables are set correctly, see:
I have set all links in VS
Having these linked to the project, I would expect MPI to work. In IDE no syntax errors are shown, MPI functions are recognized, just as in next picture. However compiling an c++ source file with MPI functions produces Undeclared identifiers errors. What do I do wrong?
Here is my code if it matters
/*
* Transmit a message in a 3-process system.
*/
#include <mpi.h>
#include "stdafx.h"
#include <stdio.h>
#include <stdlib.h>
#define BUFSIZE 10
int main(int argc, char *argv[])
{ int size, rank;
int slave;
int buf[BUFSIZE];
int n, value;
float rval;
MPI_Status status;
/* Initialize MPI */
MPI_Init(&argc, &argv);
/*
* Determine size in the world group.
*/
MPI_Comm_size(MPI_COMM_WORLD, &size);
if (size == 3) {/* Correct number of processes *}
/*
* Determine my rank in the world group.
* The master will be rank 0 and the slaves, rank 1...size-1
*/
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
if (rank == 0) { /* Master */
buf[0] = 5; buf[1] = 1; buf[2] = 8; buf[3] = 7; buf[4] = 6;
buf[5] = 5; buf[6] = 4; buf[7] = 2; buf[8] = 3; buf[9] = 1;
printf("n Sending the values {5,1,8,7,6,5,4,2,3,1}");
printf("n -----------------------------");
for (slave = 1; slave < size; slave++) {
printf("n from master %d to slave %d", rank, slave);
MPI_Send(buf, 10, MPI_INT, slave, 1, MPI_COMM_WORLD);
}
printf("nn Receiving the results from slaves");
printf("n ---------------------------------");
MPI_Recv(&value, 1, MPI_INT, 1, 11, MPI_COMM_WORLD, &status);
printf("n Minimum %4d from slave 1", value);
MPI_Recv(&value, 1, MPI_INT, 2, 21, MPI_COMM_WORLD, &status);
printf("n Sum %4d from slave 2", value);
MPI_Recv(&value, 1, MPI_INT, 1, 12, MPI_COMM_WORLD, &status);
printf("n Maximum %4d from slave 1", value);
MPI_Recv(&rval, 1, MPI_FLOAT, 2, 22, MPI_COMM_WORLD, &status);
printf("n Average %4.2f from slave 2n", rval);
}
else {
if (rank == 1) { /* minmax slave */
MPI_Recv(buf, 10, MPI_INT, 0, 1, MPI_COMM_WORLD, &status);
value = 100;
for (n = 0; n<BUFSIZE; n++) {
if (value>buf[n]) { value = buf[n]; }
}
MPI_Send(&value, 1, MPI_INT, 0, 11, MPI_COMM_WORLD);
value = 0;
for (n = 0; n<BUFSIZE; n++) {
if (value<buf[n]) { value = buf[n]; }
}
MPI_Send(&value, 1, MPI_INT, 0, 12, MPI_COMM_WORLD);
}
else { /* sumave slave */
MPI_Recv(buf, 10, MPI_INT, 0, 1, MPI_COMM_WORLD, &status);
value = 0;
for (n = 0; n<BUFSIZE; n++) {
value = value + buf[n];
}
MPI_Send(&value, 1, MPI_INT, 0, 21, MPI_COMM_WORLD);
rval = (float)value / BUFSIZE;
MPI_Send(&rval, 1, MPI_FLOAT, 0, 22, MPI_COMM_WORLD);
}
}
}
MPI_Finalize();
return(0);
}
NAME¶
Constants — Meaning of MPI’s defined constants
DATA TYPES¶
Note that the Fortran types should only be used in Fortran
programs, and the C types should only be used in C programs. For example, it
is in error to use MPI_INT for a Fortran INTEGER. Datatypes are of
type MPI_Datatype in C, type INTEGER in Fortran, and
Type(MPI_Datatype) in Fortran08
C DATATYPES¶
- MPI_CHAR
- — char
- MPI_SIGNED_CHAR
- — signed char
- MPI_UNSIGNED_CHAR
- — unsigned char
- MPI_BYTE
- — See standard; like unsigned char
- MPI_WCHAR
- — wide character (wchar_t)
- MPI_SHORT
- — short
- MPI_UNSIGNED_SHORT
- — unsigned short
- MPI_INT
- — int
- MPI_UNSIGNED
- — unsigned int
- MPI_LONG
- — long
- MPI_UNSIGNED_LONG
- — unsigned long
- MPI_LONG_LONG_INT
- — long long
- MPI_LONG_LONG
- — synonyn for MPI_LONG_LONG_INT
- MPI_UNSIGNED_LONG_LONG
- — unsigned long long
- MPI_FLOAT
- — float
- MPI_DOUBLE
- — double
- MPI_LONG_DOUBLE
- — long double (some systems may not implement this)
- MPI_INT8_T
- — int8_t
- MPI_INT16_T
- — int16_t
- MPI_INT32_T
- — int32_t
- MPI_INT64_T
- — int64_t
- MPI_UINT8_T
- — uint8_t
- MPI_UINT16_T
- — uint16_t
- MPI_UINT32_T
- — uint32_t
- MPI_UINT64_T
- — uint64_t
- MPI_C_BOOL
- — _Bool
- MPI_C_FLOAT_COMPLEX
- — float _Complex
- MPI_C_COMPLEX
- — float _Complex
- MPI_C_DOUBLE_COMPLEX
- — double _Complex
- MPI_C_LONG_DOUBLE_COMPLEX
- — long double _Complex
The following are datatypes for the MPI functions
MPI_MAXLOC and MPI_MINLOC . - MPI_FLOAT_INT
- — struct { float, int }
- MPI_LONG_INT
- — struct { long, int }
- MPI_DOUBLE_INT
- — struct { double, int }
- MPI_SHORT_INT
- — struct { short, int }
- MPI_2INT
- — struct { int, int }
- MPI_LONG_DOUBLE_INT
- — struct { long double, int } ; this is an optional type,
and may be set to MPI_DATATYPE_NULLSpecial datatypes for C and Fortran
- MPI_PACKED
- — For MPI_Pack and MPI_Unpack
- MPI_UB
- — For MPI_Type_struct ; an upper-bound indicator. Removed in MPI
3 - MPI_LB
- — For MPI_Type_struct ; a lower-bound indicator. Removed in MPI 3
FORTRAN DATATYPES¶
- MPI_REAL
- — REAL
- MPI_INTEGER
- — INTEGER
- MPI_LOGICAL
- — LOGICAL
- MPI_DOUBLE_PRECISION
- — DOUBLE PRECISION
- MPI_COMPLEX
- — COMPLEX
- MPI_DOUBLE_COMPLEX
- — complex*16 (or complex*32 ) where supported.
The following datatypes are optional
- MPI_INTEGER1
- — integer*1 if supported
- MPI_INTEGER2
- — integer*2 if supported
- MPI_INTEGER4
- — integer*4 if supported
- MPI_INTEGER8
- — integer*8 if supported
- MPI_INTEGER16
- — integer*16 if supported
- MPI_REAL4
- — real*4 if supported
- MPI_REAL8
- — real*8 if supported
- MPI_REAL16
- — real*16 if supported
- MPI_COMPLEX8
- — complex*8 if supported
- MPI_COMPLEX16
- — complex*16 if supported
- MPI_COMPLEX32
- — complex*32 if supported
The following are datatypes for the MPI functions
MPI_MAXLOC and MPI_MINLOC . In Fortran, these datatype
always consist of two elements of the same Fortran type. - MPI_2INTEGER
- — INTEGER,INTEGER
- MPI_2REAL
- — REAL, REAL
- MPI_2DOUBLE_PRECISION
- — DOUBLE PRECISION, DOUBLE PRECISION
MPI Datatypes for MPI Types
- MPI_AINT
- — Datatype for an MPI_Aint
- MPI_OFFSET
- — Datatype for an MPI_Offset
- MPI_COUNT
- — Datatype for an MPI_Count
MPI DATATYPE COMBINER NAMES¶
- MPI_COMBINER_NAMED
- — a named predefined datatype
- MPI_COMBINER_DUP
- — MPI_TYPE_DUP
- MPI_COMBINER_CONTIGUOUS
- — MPI_TYPE_CONTIGUOUS
- MPI_COMBINER_VECTOR
- — MPI_TYPE_VECTOR
- MPI_COMBINER_HVECTOR_INTEGER
- — Removed in MPI-3
- MPI_COMBINER_HVECTOR
- — MPI_TYPE_CREATE_HVECTOR
- MPI_COMBINER_INDEXED
- — MPI_TYPE_INDEXED
- MPI_COMBINER_HINDEXED_INTEGER
- — Removed in MPI-3
- MPI_COMBINER_HINDEXED
- — MPI_TYPE_CREATE_HINDEXED
- MPI_COMBINER_INDEXED_BLOCK
- — MPI_TYPE_CREATE_INDEXED_BLOCK
- MPI_COMBINER_STRUCT_INTEGER
- — Removed in MPI-3
- MPI_COMBINER_STRUCT
- — MPI_TYPE_CREATE_STRUCT
- MPI_COMBINER_SUBARRAY
- — MPI_TYPE_CREATE_SUBARRAY
- MPI_COMBINER_DARRAY
- — MPI_TYPE_CREATE_DARRAY
- MPI_COMBINER_F90_REAL
- — MPI_TYPE_CREATE_F90_REAL
- MPI_COMBINER_F90_COMPLEX
- — MPI_TYPE_CREATE_F90_COMPLEX
- MPI_COMBINER_F90_INTEGER
- — MPI_TYPE_CREATE_F90_INTEGER
- MPI_COMBINER_RESIZED
- — MPI_TYPE_CREATE_RESIZED
- MPI_COMBINER_HINDEXED_BLOCK
- — MPI_TYPE_CREATE_HINDEXED_BLOCK
MPI DATATYPE TYPE CLASSES¶
MPI Type classes used with routines to return Fortran types with
defined precision and range
- MPI_TYPECLASS_REAL
- — REAL
- MPI_TYPECLASS_INTEGER
- — INTEGER
- MPI_TYPECLASS_COMPLEX
- — COMPLEX
MPI DARRAY AND SUBARRAY VALUES¶
These values are used to create a datatype with the DARRAY
and SUBARRAY constructors.
- MPI_ORDER_C
- — Row-major order (as used by C)
- MPI_ORDER_FORTRAN
- — Column-major order (as used by Fortran)
- MPI_DISTRIBUTE_BLOCK
- — Block distribution
- MPI_DISTRIBUTE_CYCLIC
- — Cyclic distribution
- MPI_DISTRIBUTE_NONE
- — This dimension is not distributed
- MPI_DISTRIBUTE_DFLT_DARG
- — Use the default distribution
COMMUNICATORS¶
Communicators are of type MPI_Comm in C, INTEGER in
Fortran, and Type(MPI_Comm) in Fortran08
- MPI_COMM_WORLD
- — Contains all of the processes
- MPI_COMM_SELF
- — Contains only the calling process
KIND OF COMMUNICATOR FOR ‘MPI_COMM_SPLIT_TYPE’¶
- MPI_COMM_TYPE_SHARED
- — All processes that can share memory are grouped into the same
communicator.
GROUPS¶
Groups are of type MPI_Group in C, INTEGER in
Fortran, and Type(MPI_Group) in Fortran08
- MPI_GROUP_EMPTY
- — A group containing no members.
RESULTS OF THE COMPARE OPERATIONS ON GROUPS AND COMMUNICATORS¶
- MPI_IDENT
- — Identical
- MPI_CONGRUENT
- — (only for MPI_COMM_COMPARE ) The groups are identical
- MPI_SIMILAR
- — Same members, but in a different order
- MPI_UNEQUAL
- — Different
COLLECTIVE OPERATIONS¶
The collective combination operations (e.g., MPI_REDUCE ,
MPI_ALLREDUCE , MPI_REDUCE_SCATTER , and MPI_SCAN )
take a combination operation. This operation is of type MPI_Op in C
and of type INTEGER in Fortran. The predefined operations are
- MPI_MAX
- — return the maximum
- MPI_MIN
- — return the minimum
- MPI_SUM
- — return the sum
- MPI_PROD
- — return the product
- MPI_LAND
- — return the logical and
- MPI_BAND
- — return the bitwise and
- MPI_LOR
- — return the logical or
- MPI_BOR
- — return the bitwise of
- MPI_LXOR
- — return the logical exclusive or
- MPI_BXOR
- — return the bitwise exclusive or
- MPI_MINLOC
- — return the minimum and the location (actually, the value of the second
element of the structure where the minimum of the first is found) - MPI_MAXLOC
- — return the maximum and the location
- MPI_REPLACE
- — replace b with a
- MPI_NO_OP
- — perform no operation
NOTES ON COLLECTIVE OPERATIONS¶
The reduction functions ( MPI_Op ) do not return an error
value. As a result, if the functions detect an error, all they can do is
either call MPI_Abort or silently skip the problem. Thus, if you
change the error handler from MPI_ERRORS_ARE_FATAL to something else,
for example, MPI_ERRORS_RETURN , then no error may be indicated.
The reason for this is the performance problems in ensuring that
all collective routines return the same error value.
Note that not all datatypes are valid for these functions. For
example, MPI_COMPLEX is not valid for MPI_MAX and
MPI_MIN . In addition, the MPI 1.1 standard did not include the C
types MPI_CHAR and MPI_UNSIGNED_CHAR among the lists of
arithmetic types for operations like MPI_SUM . However, since the C
type char is an integer type (like short ), it should have
been included. The MPI Forum will probably include char and
unsigned char as a clarification to MPI 1.1; until then, users are
advised that MPI implementations may not accept MPI_CHAR and
MPI_UNSIGNED_CHAR as valid datatypes for MPI_SUM ,
MPI_PROD , etc. MPICH does allow these datatypes.
PERMANENT KEY VALUES¶
These are the same in C and Fortran
- MPI_TAG_UB
- — Largest tag value
- MPI_HOST
- — Rank of process that is host, if any
- MPI_IO
- — Rank of process that can do I/O
- MPI_WTIME_IS_GLOBAL
- — Has value 1 if MPI_WTIME is globally synchronized.
- MPI_UNIVERSE_SIZE
- — Number of available processes. See the standard for a description of
limitations on this value - MPI_LASTUSEDCODE
- — Last used MPI error code (check — code or class?)
- MPI_APPNUM
- — Application number, starting from 0. See the standard for
MPI_COMM_SPAWN_MULTIPLE and mpiexec for details
NULL OBJECTS¶
- MPI_COMM_NULL
- — Null communicator
- MPI_OP_NULL
- — Null operation
- MPI_GROUP_NULL
- — Null group
- MPI_DATATYPE_NULL
- — Null datatype
- MPI_REQUEST_NULL
- — Null request
- MPI_ERRHANDLER_NULL
- — Null error handler
- MPI_WIN_NULL
- — Null window handle
- MPI_FILE_NULL
- — Null file handle
- MPI_INFO_NULL
- — Null info handle
- MPI_MESSAGE_NULL
- — Null message handle
- MPI_ARGV_NULL
- — Empty ARGV value for spawn commands
- MPI_ARGVS_NULL
- — Empty ARGV array for spawn-multiple command
- MPI_T_ENUM_NULL
- — Null MPI_T enum
- MPI_T_CVAR_HANDLE_NULL
- — Null MPI_T control variable handle
- MPI_T_PVAR_HANDLE_NULL
- — Null MPI_T performance variable handle
- MPI_T_PVAR_SESSION_NULL
- — Null MPI_T performance variable session handle
PREDEFINED CONSTANTS¶
- MPI_MAX_PROCESSOR_NAME
- — Maximum length of name returned by MPI_GET_PROCESSOR_NAME
- MPI_MAX_ERROR_STRING
- — Maximum length of string return by MPI_ERROR_STRING
- MPI_MAX_LIBRARY_VERSION_STRING
- — Maximum length of string returned by
MPI_GET_LIBRARY_VERSION_STRING ??? - MPI_MAX_PORT_NAME
- — Maximum length of a port
- MPI_MAX_OBJECT_NAME
- — Maximum length of an object (?)
- MPI_MAX_INFO_KEY
- — Maximum length of an info key
- MPI_MAX_INFO_VAL
- — Maximum length of an info value
- MPI_UNDEFINED
- — Used by many routines to indicated undefined or unknown integer
value - MPI_UNDEFINED_RANK
- — Unknown rank
- MPI_KEYVAL_INVALID
- — Special keyval that may be used to detect uninitialized keyvals.
- MPI_BSEND_OVERHEAD
- — Add this to the size of a MPI_BSEND buffer for each outstanding
message - MPI_PROC_NULL
- — This rank may be used to send or receive from no-one.
- MPI_ANY_SOURCE
- — In a receive, accept a message from anyone.
- MPI_ANY_TAG
- — In a receive, accept a message with any tag value.
- MPI_BOTTOM
- — May be used to indicate the bottom of the address space
- MPI_IN_PLACE
- — Special location for buffer in some collective communication
routines - MPI_VERSION
- — Numeric value of MPI version (e.g., 3)
- MPI_SUBVERSION
- — Numeric value of MPI subversion (e.g., 1)
TOPOLOGY TYPES¶
- MPI_CART
- — Cartesian grid
- MPI_GRAPH
- — General graph
- MPI_DIST_GRAPH
- — General distributed graph
SPECIAL VALUES FOR DISTRIBUTED GRAPH¶
- MPI_UNWEIGHTED
- — Indicates that the edges are unweighted
- MPI_WEIGHTS_EMPTY
- — Special address that indicates no array of weights information
FILE MODES¶
- MPI_MODE_RDONLY
- — Read only
- MPI_MODE_RDWR
- — Read and write
- MPI_MODE_WRONLY
- — Write only
- MPI_MODE_CREATE
- — Create the file if it does not exist
- MPI_MODE_EXCL
- — It is an error if creating a file that already exists
- MPI_MODE_DELETE_ON_CLOSE
- — Delete the file on close
- MPI_MODE_UNIQUE_OPEN
- — The file will not be concurrently opened elsewhere
- MPI_MODE_APPEND
- — The initial position of all file pointers is at the end of the file
- MPI_MODE_SEQUENTIAL
- — File will only be accessed sequentially
FILE DISPLACEMENT¶
- MPI_DISPLACEMENT_CURRENT
- — Use with files opened with mode MPI_MODE_SEQUENTIAL in calls to
MPI_FILE_SET_VIEW
FILE POSITIONING¶
- MPI_SEEK_SET
- — Set the pointer to offset
- MPI_SEEK_CUR
- — Set the pointer to the current position plus offset
- MPI_SEEK_END
- — Set the pointer to the end of the file plus offset
WINDOW ATTRIBUTES¶
- MPI_WIN_BASE
- — window base address.
- MPI_WIN_SIZE
- — window size, in bytes
- MPI_WIN_DISP_UNIT
- — displacement unit associated with the window
- MPI_WIN_CREATE_FLAVOR
- — how the window was created
- MPI_WIN_MODEL
- — memory model for window
WINDOW FLAVORS¶
- MPI_WIN_FLAVOR_CREATE
- — Window was created with MPI_WIN_CREATE.
- MPI_WIN_FLAVOR_ALLOCATE
- — Window was created with MPI_WIN_ALLOCATE.
- MPI_WIN_FLAVOR_DYNAMIC
- — Window was created with MPI_WIN_CREATE_DYNAMIC.
- MPI_WIN_FLAVOR_SHARED
- — Window was created with MPI_WIN_ALLOCATE_SHARED.
WINDOW MEMORY MODEL¶
- MPI_WIN_SEPARATE
- — Separate public and private copies of window memory
- MPI_WIN_UNIFIED
- — The public and private copies are identical (by which we mean that
updates are eventually observed without additional RMA operations)
WINDOW LOCK TYPES¶
- MPI_LOCK_EXCLUSIVE
- — Only one process at a time will execute accesses within the lock
- MPI_LOCK_SHARED
- — Not exclusive; multiple processes may execute accesses within the lock
WINDOW ASSERTIONS¶
See section 11.5 in MPI 3.1 for a detailed description of each of
these assertion values.
- MPI_MODE_NOCHECK
- — The matching calls to MPI_WIN_POST or MPI_WIN_START have already
completed, or no process holds or will attempt to acquire, a conflicting
lock. - MPI_MODE_NOSTORE
- — The local window has not been updated by stores since the last
synchronization - MPI_MODE_NOPUT
- — The local window will not be updated by put or accumulate until the next
synchronization - MPI_MODE_NOPRECEDE
- — The fence does not complete any locally issued RMA calls
- MPI_MODE_NOSUCCEED
- — The fence does not start any locally issued RMA calls
PREDEFINED INFO OBJECT¶
- MPI_INFO_ENV
- — Contains the execution environment
MPI STATUS¶
The MPI_Status datatype is a structure in C. The three
elements for use by programmers are
- MPI_SOURCE
- — Who sent the message
- MPI_TAG
- — What tag the message was sent with
- MPI_ERROR
- — Any error return (only when the error returned by the routine has error
class MPI_ERR_IN_STATUS ) - MPI_STATUS_IGNORE
- — Ignore a single MPI_Status argument
- MPI_STATUSES_IGNORE
- — Ignore an array of MPI_Status
SPECIAL VALUE FOR ERROR CODES ARRAY¶
- MPI_ERRCODES_IGNORE
- — Ignore an array of error codes
MPI_T CONSTANTS¶
- MPI_T_VERBOSITY_USER_BASIC
- — Basic information of interest to users
- MPI_T_VERBOSITY_USER_DETAIL
- — Detailed information of interest to users
- MPI_T_VERBOSITY_USER_ALL
- — All remaining information of interest to users
- MPI_T_VERBOSITY_TUNER_BASIC
- — Basic information required for tuning
- MPI_T_VERBOSITY_TUNER_DETAIL
- — Detailed information required for tuning
- MPI_T_VERBOSITY_TUNER_ALL
- — All remaining information required for tuning
- MPI_T_VERBOSITY_MPIDEV_BASIC
- — Basic information for MPI implementors
- MPI_T_VERBOSITY_MPIDEV_DETAIL
- — Detailed information for MPI implementors
- MPI_T_VERBOSITY_MPIDEV_ALL
- — All remaining information for MPI implementors
- MPI_T_BIND_NO_OBJECT
- — Applies globally to entire MPI process
- MPI_T_BIND_MPI_COMM
- — MPI communicators
- MPI_T_BIND_MPI_DATATYPE
- — MPI datatypes
- MPI_T_BIND_MPI_ERRHANDLER
- — MPI error handlers
- MPI_T_BIND_MPI_FILE
- — MPI file handles
- MPI_T_BIND_MPI_GROUP
- — MPI groups
- MPI_T_BIND_MPI_OP
- — MPI reduction operators
- MPI_T_BIND_MPI_REQUEST
- — MPI requests
- MPI_T_BIND_MPI_WIN
- — MPI windows for one-sided communication
- MPI_T_BIND_MPI_MESSAGE
- — MPI message object
- MPI_T_BIND_MPI_INFO
- — MPI info object
- MPI_T_SCOPE_CONSTANT
- — read-only, value is constant
- MPI_T_SCOPE_READONLY
- — read-only, cannot be written, but can change
- MPI_T_SCOPE_LOCAL
- — may be writeable, writing is a local operation
- MPI_T_SCOPE_GROUP
- — may be writeable, must be done to a group of processes, all processes in
a group must be set to consistent values - MPI_T_SCOPE_GROUP_EQ
- — may be writeable, must be done to a group of processes, all processes in
a group must be set to the same value - MPI_T_SCOPE_ALL
- — may be writeable, must be done to all processes, all connected processes
must be set to consistent values - MPI_T_SCOPE_ALL_EQ
- — may be writeable, must be done to all processes, all connected processes
must be set to the same value - MPI_T_PVAR_CLASS_STATE
- — set of discrete states (MPI_INT)
- MPI_T_PVAR_CLASS_LEVEL
- — utilization level of a resource
- MPI_T_PVAR_CLASS_SIZE
- — size of a resource
- MPI_T_PVAR_CLASS_PERCENTAGE
- — percentage utilization of a resource
- MPI_T_PVAR_CLASS_HIGHWATERMARK
- — high watermark of a resource
- MPI_T_PVAR_CLASS_LOWWATERMARK
- — low watermark of a resource
- MPI_T_PVAR_CLASS_COUNTER
- — number of occurrences of an event
- MPI_T_PVAR_CLASS_AGGREGATE
- — aggregate value over an event (e.g., sum of all memory allocations)
- MPI_T_PVAR_CLASS_TIMER
- — aggretate time spent executing event
- MPI_T_PVAR_CLASS_GENERIC
- — used for any other time of performance variable
THREAD LEVELS¶
- MPI_THREAD_SINGLE
- — Only one thread executes
- MPI_THREAD_FUNNELED
- — Only the main thread makes MPI calls
- MPI_THREAD_SERIALIZED
- — Only one thread at a time makes MPI calls
- MPI_THREAD_MULTIPLE
- — Multiple threads may make MPI calls
SPECIAL MPI TYPES AND FUNCTIONS¶
- MPI_Aint
- — C type that holds any valid address.
- MPI_Count
- — C type that holds any valid count.
- MPI_Offset
- — C type that holds any valid file offset.
- MPI_Handler_function
- — C function for handling errors (see MPI_Errhandler_create )
. - MPI_User_function
- — C function to combine values (see collective operations and
MPI_Op_create ) - MPI_Copy_function
- — Function to copy attributes (see MPI_Keyval_create )
- MPI_Delete_function
- — Function to delete attributes (see MPI_Keyval_create )
- MPI_ERRORS_ARE_FATAL
- — Error handler that forces exit on error
- MPI_ERRORS_RETURN
- — Error handler that returns error codes (as value of MPI routine in C and
through last argument in Fortran) - MPI_ERRORS_ABORT
- — Error handler that forces exit on error (only aborts local process if
the error handler is invoked on a session)
MPI ATTRIBUTE DEFAULT FUNCTIONS¶
- MPI_COMM_NULL_COPY_FN
- — Predefined attribute copy function for communicators
- MPI_COMM_NULL_DELETE_FN
- — Predefined attribute delete function for communicators
- MPI_COMM_DUP_FN
- — Predefined attribute duplicate function for communicators
- MPI_WIN_NULL_COPY_FN
- — Predefined attribute copy function for windows
- MPI_WIN_NULL_DELETE_FN
- — Predefined attribute delete function for windows
- MPI_WIN_DUP_FN
- — Predefined attribute duplicate function for windows
- MPI_TYPE_NULL_COPY_FN
- — Predefined attribute copy function for datatypes
- MPI_TYPE_NULL_DELETE_FN
- — Predefined attribute delete function for datatypes
- MPI_TYPE_DUP_FN
- — Predefined attribute duplicate function for datatypes
MPI-1 ATTRIBUTE DEFAULT FUNCTIONS¶
- MPI_NULL_COPY_FN
- — Predefined copy function
- MPI_NULL_DELETE_FN
- — Predefined delete function
- MPI_DUP_FN
- — Predefined duplication function
MPI ERROR CLASSES¶
- MPI_SUCCESS
- — Successful return code
- MPI_ERR_BUFFER
- — Invalid buffer pointer
- MPI_ERR_COUNT
- — Invalid count argument
- MPI_ERR_TYPE
- — Invalid datatype argument
- MPI_ERR_TAG
- — Invalid tag argument
- MPI_ERR_COMM
- — Invalid communicator
- MPI_ERR_RANK
- — Invalid rank
- MPI_ERR_ROOT
- — Invalid root
- MPI_ERR_GROUP
- — Null group passed to function
- MPI_ERR_OP
- — Invalid operation
- MPI_ERR_TOPOLOGY
- — Invalid topology
- MPI_ERR_DIMS
- — Illegal dimension argument
- MPI_ERR_ARG
- — Invalid argument
- MPI_ERR_UNKNOWN
- — Unknown error
- MPI_ERR_TRUNCATE
- — Message truncated on receive
- MPI_ERR_OTHER
- — Other error; use Error_string
- MPI_ERR_INTERN
- — Internal error code
- MPI_ERR_IN_STATUS
- — Look in status for error value
- MPI_ERR_PENDING
- — Pending request
- MPI_ERR_REQUEST
- — Invalid mpi_request handle
- MPI_ERR_ACCESS
- — Permission denied
- MPI_ERR_AMODE
- — Error related to the amode passed to MPI_FILE_OPEN
- MPI_ERR_BAD_FILE
- — Invalid file name (e.g., path name too long)
- MPI_ERR_CONVERSION
- — An error occurred in a user supplied data conversion function
- MPI_ERR_DUP_DATAREP
- — Conversion functions could not be registered because a data
representation identifier that was already defined was passed to
MPI_REGISTER_DATAREP - MPI_ERR_FILE_EXISTS
- — File exists
- MPI_ERR_FILE_IN_USE
- — File operation could not be completed, as the file is currently open by
some process - MPI_ERR_FILE
- — Invalid file handle
- MPI_ERR_IO
- — Other I/O error
- MPI_ERR_NO_SPACE
- — Not enough space
- MPI_ERR_NO_SUCH_FILE
- — File does not exist
- MPI_ERR_READ_ONLY
- — Read-only file or file system
- MPI_ERR_UNSUPPORTED_DATAREP
- — Unsupported datarep passed to MPI_FILE_SET_VIEW
- MPI_ERR_INFO
- — Invalid info argument
- MPI_ERR_INFO_KEY
- — Key longer than MPI_MAX_INFO_KEY
- MPI_ERR_INFO_VALUE
- — Value longer than MPI_MAX_INFO_VAL
- MPI_ERR_INFO_NOKEY
- — Invalid key passed to MPI_INFO_DELETE
- MPI_ERR_NAME
- — Invalid service name passed to MPI_LOOKUP_NAME
- MPI_ERR_NO_MEM
- — Alloc_mem could not allocate memory
- MPI_ERR_NOT_SAME
- — Collective argument not identical on all processes, or collective
routines called in a different order by different processes - MPI_ERR_PORT
- — Invalid port name passed to MPI_COMM_CONNECT
- MPI_ERR_QUOTA
- — Quota exceeded
- MPI_ERR_SERVICE
- — Invalid service name passed to MPI_UNPUBLISH_NAME
- MPI_ERR_SPAWN
- — Error in spawning processes
- MPI_ERR_UNSUPPORTED_OPERATION
- — Unsupported operation, such as seeking on a file which supports
sequential access only - MPI_ERR_WIN
- — Invalid win argument
- MPI_ERR_BASE
- — Invalid base passed to MPI_FREE_MEM
- MPI_ERR_LOCKTYPE
- — Invalid locktype argument
- MPI_ERR_KEYVAL
- — Erroneous attribute key
- MPI_ERR_RMA_CONFLICT
- — Conflicting accesses to window
- MPI_ERR_RMA_SYNC
- — Wrong synchronization of RMA calls
- MPI_ERR_SIZE
- — Invalid size argument
- MPI_ERR_DISP
- — Invalid disp argument
- MPI_ERR_ASSERT
- — Invalid assert argument
- MPI_ERR_RMA_RANGE
- — Target memory is not part of the window (in the case of a window created
with MPI_WIN_CREATE_DYNAMIC, target memory is not attached) - MPI_ERR_RMA_ATTACH
- — Memory cannot be attached (e.g., because of resource exhaustion)
- MPI_ERR_RMA_SHARED
- — Memory cannot be shared (e.g., some process in the group of the
specified communicator cannot expose shared memory) - MPI_ERR_RMA_FLAVOR
- — Passed window has the wrong flavor for the called function
- MPI_ERR_LASTCODE
- — Last error code — always at end
ERROR CODES FOR MPI_T¶
- MPI_T_ERR_MEMORY
- — Out of memory
- MPI_T_ERR_NOT_INITIALIZED
- — Interface not initialized
- MPI_T_ERR_CANNOT_INIT
- — Interface not in the state to be initialized
- MPI_T_ERR_INVALID_INDEX
- — The index is invalid or has been deleted
- MPI_T_ERR_INVALID_HANDLE
- — The handle is invalid
- MPI_T_ERR_OUT_OF_HANDLES
- — No more handles available
- MPI_T_ERR_OUT_OF_SESSIONS
- — No more sessions available
- MPI_T_ERR_INVALID_SESSION
- — Session argument is not valid
- MPI_T_ERR_CVAR_SET_NOT_NOW
- — Cvar cannot be set at this moment
- MPI_T_ERR_CVAR_SET_NEVER
- — Cvar cannot be set until end of execution
- MPI_T_ERR_PVAR_NO_STARTSTOP
- — Pvar can’t be started or stopped
- MPI_T_ERR_PVAR_NO_WRITE
- — Pvar can’t be written or reset
- MPI_T_ERR_PVAR_NO_ATOMIC
- — Pvar can’t be R/W atomically
- MPI_T_ERR_INVALID_NAME
- — Name doesn’t match
- MPI_T_ERR_INVALID
- — Invalid use of the interface or bad parameter values(s)
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and
privacy statement. We’ll occasionally send you account related emails.
Already on GitHub?
Sign in
to your account
Closed
Mosseridan opened this issue
Jul 5, 2018
· 11 comments
Comments
Hello.
I am getting MPI errors when trying to compile scm with both spack and cmake.
Here is the the cmake output:
cmake -DWITH_PDSH_PREFIX=/home/idanmos/scr/pdsh_ins -DWITH_DTCMP_PREFIX=/home/idanmos/scr/dtcmp_ins -DCMAKE_INSTALL_PREFIX=../scr_ins ../scr -- The C compiler identification is GNU 4.8.5 -- The CXX compiler identification is GNU 4.8.5 -- Check for working C compiler: /usr/bin/cc -- Check for working C compiler: /usr/bin/cc -- works -- Detecting C compiler ABI info -- Detecting C compiler ABI info - done -- Check for working CXX compiler: /usr/bin/c++ -- Check for working CXX compiler: /usr/bin/c++ -- works -- Detecting CXX compiler ABI info -- Detecting CXX compiler ABI info - done -- The Fortran compiler identification is GNU -- Check for working Fortran compiler: /usr/bin/gfortran -- Check for working Fortran compiler: /usr/bin/gfortran -- works -- Detecting Fortran compiler ABI info -- Detecting Fortran compiler ABI info - done -- Checking whether /usr/bin/gfortran supports Fortran 90 -- Checking whether /usr/bin/gfortran supports Fortran 90 -- yes -- Found MPI_C: /usr/lib64/openmpi/lib/libmpi.so -- Found MPI_CXX: /usr/lib64/openmpi/lib/libmpi_cxx.so;/usr/lib64/openmpi/lib/libmpi.so -- Found MPI_Fortran: /usr/lib64/openmpi/lib/libmpi_usempi.so;/usr/lib64/openmpi/lib/libmpi_mpifh.so;/usr/lib64/openmpi/lib/libmpi.so -- MPI C Compile Flags: -- MPI C Include Path: /usr/include/openmpi-x86_64 -- MPI C Link Flags: -Wl,-rpath -Wl,/usr/lib64/openmpi/lib -Wl,--enable-new-dtags -- MPI C Libraries: /usr/lib64/openmpi/lib/libmpi.so -- MPI CXX Compile Flags: -- MPI CXX Include Path: /usr/include/openmpi-x86_64 -- MPI CXX Link Flags: -Wl,-rpath -Wl,/usr/lib64/openmpi/lib -Wl,--enable-new-dtags -- MPI CXX Libraries: /usr/lib64/openmpi/lib/libmpi_cxx.so;/usr/lib64/openmpi/lib/libmpi.so -- MPI Executable: /usr/lib64/openmpi/bin/mpiexec -- MPI Num Proc Flag: -np -- Using MPI Fortran header: mpif.h -- Found ZLIB: /usr/lib64/libz.so (found version "1.2.7") -- Looking for byteswap.h -- Looking for byteswap.h - found -- Found PDSH: /home/idanmos/scr/pdsh_ins/bin/pdsh -- Configuring done -- Generating done -- Build files have been written to: /home/idanmos/scr/scr_bld [idanmos@Printer scr_bld]$ make Scanning dependencies of target scr_o [ 1%] Building C object src/CMakeFiles/scr_o.dir/scr.c.o /home/idanmos/scr/scr/src/scr.c: In function ‘scr_start_output’: /home/idanmos/scr/scr/src/scr.c:966:24: warning: initialization discards ‘const’ qualifier from pointer target type [enabled by default] char* dataset_name = name; ^ [ 2%] Building C object src/CMakeFiles/scr_o.dir/scr_cache.c.o [ 3%] Building C object src/CMakeFiles/scr_o.dir/scr_cache_rebuild.c.o [ 5%] Building C object src/CMakeFiles/scr_o.dir/scr_compress.c.o [ 6%] Building C object src/CMakeFiles/scr_o.dir/scr_config.c.o [ 7%] Building C object src/CMakeFiles/scr_o.dir/scr_config_mpi.c.o [ 8%] Building C object src/CMakeFiles/scr_o.dir/scr_dataset.c.o [ 10%] Building C object src/CMakeFiles/scr_o.dir/scr_env.c.o [ 11%] Building C object src/CMakeFiles/scr_o.dir/scr_err_mpi.c.o [ 12%] Building C object src/CMakeFiles/scr_o.dir/scr_fetch.c.o [ 13%] Building C object src/CMakeFiles/scr_o.dir/scr_filemap.c.o [ 15%] Building C object src/CMakeFiles/scr_o.dir/scr_flush.c.o [ 16%] Building C object src/CMakeFiles/scr_o.dir/scr_flush_file_mpi.c.o [ 17%] Building C object src/CMakeFiles/scr_o.dir/scr_flush_sync.c.o [ 18%] Building C object src/CMakeFiles/scr_o.dir/scr_globals.c.o [ 20%] Building C object src/CMakeFiles/scr_o.dir/scr_groupdesc.c.o [ 21%] Building C object src/CMakeFiles/scr_o.dir/scr_halt.c.o [ 22%] Building C object src/CMakeFiles/scr_o.dir/scr_hash.c.o [ 23%] Building C object src/CMakeFiles/scr_o.dir/scr_hash_mpi.c.o [ 25%] Building C object src/CMakeFiles/scr_o.dir/scr_hash_util.c.o [ 26%] Building C object src/CMakeFiles/scr_o.dir/scr_index_api.c.o [ 27%] Building C object src/CMakeFiles/scr_o.dir/scr_io.c.o [ 28%] Building C object src/CMakeFiles/scr_o.dir/scr_log.c.o [ 30%] Building C object src/CMakeFiles/scr_o.dir/scr_meta.c.o [ 31%] Building C object src/CMakeFiles/scr_o.dir/scr_param.c.o [ 32%] Building C object src/CMakeFiles/scr_o.dir/scr_path.c.o [ 33%] Building C object src/CMakeFiles/scr_o.dir/scr_path_mpi.c.o [ 35%] Building C object src/CMakeFiles/scr_o.dir/scr_reddesc.c.o [ 36%] Building C object src/CMakeFiles/scr_o.dir/scr_reddesc_apply.c.o [ 37%] Building C object src/CMakeFiles/scr_o.dir/scr_reddesc_recover.c.o [ 38%] Building C object src/CMakeFiles/scr_o.dir/scr_split.c.o [ 40%] Building C object src/CMakeFiles/scr_o.dir/scr_storedesc.c.o [ 41%] Building C object src/CMakeFiles/scr_o.dir/scr_summary.c.o [ 42%] Building C object src/CMakeFiles/scr_o.dir/scr_util.c.o [ 43%] Building C object src/CMakeFiles/scr_o.dir/scr_util_mpi.c.o [ 45%] Building C object src/CMakeFiles/scr_o.dir/tv_data_display.c.o [ 46%] Building C object src/CMakeFiles/scr_o.dir/scr_flush_async_posix.c.o [ 46%] Built target scr_o Scanning dependencies of target scr Linking C shared library libscr.so [ 46%] Built target scr Scanning dependencies of target scr-static Linking C static library libscr.a [ 46%] Built target scr-static Scanning dependencies of target scr_base [ 47%] Building C object src/CMakeFiles/scr_base.dir/scr_compress.c.o [ 48%] Building C object src/CMakeFiles/scr_base.dir/scr_config.c.o [ 50%] Building C object src/CMakeFiles/scr_base.dir/scr_config_serial.c.o [ 51%] Building C object src/CMakeFiles/scr_base.dir/scr_dataset.c.o [ 52%] Building C object src/CMakeFiles/scr_base.dir/scr_env.c.o [ 53%] Building C object src/CMakeFiles/scr_base.dir/scr_err_serial.c.o [ 55%] Building C object src/CMakeFiles/scr_base.dir/scr_filemap.c.o [ 56%] Building C object src/CMakeFiles/scr_base.dir/scr_halt.c.o [ 57%] Building C object src/CMakeFiles/scr_base.dir/scr_hash.c.o [ 58%] Building C object src/CMakeFiles/scr_base.dir/scr_hash_util.c.o [ 60%] Building C object src/CMakeFiles/scr_base.dir/scr_index_api.c.o [ 61%] Building C object src/CMakeFiles/scr_base.dir/scr_io.c.o [ 62%] Building C object src/CMakeFiles/scr_base.dir/scr_log.c.o [ 63%] Building C object src/CMakeFiles/scr_base.dir/scr_meta.c.o [ 65%] Building C object src/CMakeFiles/scr_base.dir/scr_param.c.o [ 66%] Building C object src/CMakeFiles/scr_base.dir/scr_path.c.o [ 67%] Building C object src/CMakeFiles/scr_base.dir/scr_util.c.o [ 68%] Building C object src/CMakeFiles/scr_base.dir/tv_data_display.c.o Linking C static library libscr_base.a [ 68%] Built target scr_base Scanning dependencies of target scr_copy [ 70%] Building C object src/CMakeFiles/scr_copy.dir/scr_copy.c.o Linking C executable scr_copy [ 70%] Built target scr_copy Scanning dependencies of target scr_crc32 [ 71%] Building C object src/CMakeFiles/scr_crc32.dir/scr_crc32.c.o Linking C executable scr_crc32 [ 71%] Built target scr_crc32 Scanning dependencies of target scr_flush_file [ 72%] Building C object src/CMakeFiles/scr_flush_file.dir/scr_flush_file.c.o Linking C executable scr_flush_file [ 72%] Built target scr_flush_file Scanning dependencies of target scr_halt_cntl [ 73%] Building C object src/CMakeFiles/scr_halt_cntl.dir/scr_halt_cntl.c.o Linking C executable scr_halt_cntl [ 73%] Built target scr_halt_cntl Scanning dependencies of target scr_have_restart [ 75%] Building C object src/CMakeFiles/scr_have_restart.dir/scr_have_restart.c.o Linking C executable scr_have_restart [ 75%] Built target scr_have_restart Scanning dependencies of target scr_index [ 76%] Building C object src/CMakeFiles/scr_index.dir/scr_index.c.o Linking C executable scr_index [ 76%] Built target scr_index Scanning dependencies of target scr_inspect_cache [ 77%] Building C object src/CMakeFiles/scr_inspect_cache.dir/scr_inspect_cache.c.o Linking C executable scr_inspect_cache [ 77%] Built target scr_inspect_cache Scanning dependencies of target scr_log_event [ 78%] Building C object src/CMakeFiles/scr_log_event.dir/scr_log_event.c.o Linking C executable scr_log_event [ 78%] Built target scr_log_event Scanning dependencies of target scr_log_transfer [ 80%] Building C object src/CMakeFiles/scr_log_transfer.dir/scr_log_transfer.c.o Linking C executable scr_log_transfer [ 80%] Built target scr_log_transfer Scanning dependencies of target scr_nodes_file [ 81%] Building C object src/CMakeFiles/scr_nodes_file.dir/scr_nodes_file.c.o Linking C executable scr_nodes_file [ 81%] Built target scr_nodes_file Scanning dependencies of target scr_print_hash_file [ 82%] Building C object src/CMakeFiles/scr_print_hash_file.dir/scr_print_hash_file.c.o Linking C executable scr_print_hash_file [ 82%] Built target scr_print_hash_file Scanning dependencies of target scr_rebuild_xor [ 83%] Building C object src/CMakeFiles/scr_rebuild_xor.dir/scr_rebuild_xor.c.o Linking C executable scr_rebuild_xor [ 83%] Built target scr_rebuild_xor Scanning dependencies of target scr_retries_halt [ 85%] Building C object src/CMakeFiles/scr_retries_halt.dir/scr_retries_halt.c.o Linking C executable scr_retries_halt [ 85%] Built target scr_retries_halt Scanning dependencies of target scr_transfer [ 86%] Building C object src/CMakeFiles/scr_transfer.dir/scr_transfer.c.o Linking C executable scr_transfer [ 86%] Built target scr_transfer Scanning dependencies of target scrf [ 87%] Building C object src/CMakeFiles/scrf.dir/scrf.c.o Linking C shared library libscrf.so [ 87%] Built target scrf Scanning dependencies of target scrf-static [ 88%] Building C object src/CMakeFiles/scrf-static.dir/scrf.c.o Linking C static library libscrf.a [ 88%] Built target scrf-static Scanning dependencies of target test_api [ 90%] Building C object examples/CMakeFiles/test_api.dir/test_common.c.o [ 91%] Building C object examples/CMakeFiles/test_api.dir/test_api.c.o Linking C executable test_api [ 91%] Built target test_api Scanning dependencies of target test_api_multiple [ 92%] Building C object examples/CMakeFiles/test_api_multiple.dir/test_common.c.o [ 93%] Building C object examples/CMakeFiles/test_api_multiple.dir/test_api_multiple.c.o Linking C executable test_api_multiple [ 93%] Built target test_api_multiple Scanning dependencies of target test_ckpt_C [ 95%] Building CXX object examples/CMakeFiles/test_ckpt_C.dir/test_ckpt.C.o Linking CXX executable test_ckpt_C CMakeFiles/test_ckpt_C.dir/test_ckpt.C.o: In function
MPI::Intracomm::Intracomm()’:
test_ckpt.C:(.text._ZN3MPI9IntracommC2Ev[_ZN3MPI9IntracommC5Ev]+0x14): undefined reference to MPI::Comm::Comm()' CMakeFiles/test_ckpt_C.dir/test_ckpt.C.o: In function
MPI::Intracomm::Intracomm(ompi_communicator_t*)’:
test_ckpt.C:(.text._ZN3MPI9IntracommC2EP19ompi_communicator_t[_ZN3MPI9IntracommC5EP19ompi_communicator_t]+0x19): undefined reference to MPI::Comm::Comm()' CMakeFiles/test_ckpt_C.dir/test_ckpt.C.o: In function
MPI::Op::Init(void ()(void const, void*, int, MPI::Datatype const&), bool)’:
test_ckpt.C:(.text._ZN3MPI2Op4InitEPFvPKvPviRKNS_8DatatypeEEb[_ZN3MPI2Op4InitEPFvPKvPviRKNS_8DatatypeEEb]+0x26): undefined reference to ompi_mpi_cxx_op_intercept' CMakeFiles/test_ckpt_C.dir/test_ckpt.C.o:(.data.rel.ro._ZTVN3MPI3WinE[_ZTVN3MPI3WinE]+0x48): undefined reference to
MPI::Win::Free()’
CMakeFiles/test_ckpt_C.dir/test_ckpt.C.o:(.data.rel.ro._ZTVN3MPI8DatatypeE[_ZTVN3MPI8DatatypeE]+0x78): undefined reference to MPI::Datatype::Free()' collect2: error: ld returned 1 exit status make[2]: *** [examples/test_ckpt_C] Error 1 make[1]: *** [examples/CMakeFiles/test_ckpt_C.dir/all] Error 2 make: *** [all] Error 2
the spack log is also attached here:
spack-build.TXT
would greatly appreciate your help.
thank’s.
Idan
Hmm. The C++ bindings were removed in MPI-3.0 in 2012. They are not built by default from Open MPI v3.0.0+ and will be removed entirely in v5.0.0.
So sould I install an earlier version of open mpi? And if so what veraion would you recommend? What do you think i should do to fix this bug?
Thanks for your help @hjelmn .
@Mosseridan , from the SCR side, we’ll need to drop the test case that uses the C++ bindings for MPI and make a new release available for spack. That will take us some time to put together. We could get a fix to you faster if you don’t mind building from the master branch.
Do you mind doing that?
Otherwise, I think a faster solution would be to build Open MPI with C++ bindings. It looks to me like you’re building with a system install of Open MPI:
Based on the output here, it looks like the compile step worked, but it failed on the link step:
Linking CXX executable test_ckpt_C CMakeFiles/test_ckpt_C.dir/test_ckpt.C.o: In functionMPI::Intracomm::Intracomm()':
test_ckpt.C:(.text._ZN3MPI9IntracommC2Ev[_ZN3MPI9IntracommC5Ev]+0x14): undefined reference to MPI::Comm::Comm()'
That can happen if it finds the C++ headers at compile time, but misses the necessary library with -l during link. However, I do see earlier on that cmake found the Open MPI C++ library:
Found MPI_CXX: /usr/lib64/openmpi/lib/libmpi_cxx.so;
C++ compilers sometimes change how they mangle names across compiler versions. If the Open MPI was built with one compiler, SCR might not be able to find the symbols at link time if it is built with a different compiler. It looks like you’re building SCR with 4.8.5.
Do you know what your Open MPI install was compiled with?
Oh, in file you attached for the pure spack build, there are other clues. There, I can see that it’s building both SCR and Open MPI with the same compiler, and it has detected the Open MPI C++ library, but I can see that it’s missing from the link line. So that might be a problem in the SCR cmake files. Let me check.
The SCR CMake files don’t link to the MPI C++ libraries (under the assumption that they deprecated). To fix this, add the following in the toplevel CMakeLists.txt
file:
IF(MPI_CXX_FOUND)
INCLUDE_DIRECTORIES(${MPI_CXX_INCLUDE_PATH})
LIST(APPEND SCR_EXTERNAL_LIBS ${MPI_CXX_LIBRARIES})
ENDIF(MPI_CXX_FOUND)
After the INCLUDE(SetupMPI)
line.
@hjelmn , so the test_ckpt.C file does not use the MPI C++ interface. It is a C++ program, but it uses the MPI C interface. However, it apparently picks up some C++ interface dependencies from some Open MPI headers. I suppose we could fix this by linking in the Open MPI C++ library, but it’s not clear whether that’s the right thing to do.
Can you take a look and comment?
Here is the compile line from spack:
[ 85%] Building CXX object examples/CMakeFiles/test_ckpt_C.dir/test_ckpt.C.o
cd /tmp/idanmos/spack-stage/spack-stage-lvrt51w9/scr-1.2.0/spack-build/examples && /home/idanmos/spack/lib/spack/env/gcc/g++ -I/home/idanmos/spack/opt/spack/linux-centos7-x86_64/gcc-4.8.5/openmpi-3.1.0-wihq6ns5dpzoja3hm5gvzpxijprv7wh7/include -I/home/idanmos/spack/opt/spack/linux-centos7-x86_64/gcc-4.8.5/zlib-1.2.11-64vg6e4evdrlqgx7iicwhu2hs7lv6gpz/include -I/home/idanmos/spack/opt/spack/linux-centos7-x86_64/gcc-4.8.5/dtcmp-1.1.0-z5diekaxgk42rxabqrq6v3hkp2a2g2c6/include -I/home/idanmos/spack/opt/spack/linux-centos7-x86_64/gcc-4.8.5/libyogrt-1.20-6-tcm7yxo23glyoabtxjceah4y3ghzpjx6/include -I/home/idanmos/spack/var/spack/stage/scr-1.2.0-u6em5mwaawncs5g4634fjiqo3kfwk2xd/scr-1.2.0/src -I/home/idanmos/spack/var/spack/stage/scr-1.2.0-u6em5mwaawncs5g4634fjiqo3kfwk2xd/scr-1.2.0/examples -O2 -g -DNDEBUG -fPIE -o CMakeFiles/test_ckpt_C.dir/test_ckpt.C.o -c /home/idanmos/spack/var/spack/stage/scr-1.2.0-u6em5mwaawncs5g4634fjiqo3kfwk2xd/scr-1.2.0/examples/test_ckpt.C
And the link line, along with some of the errors:
[100%] Linking CXX executable test_ckpt_C
cd /tmp/idanmos/spack-stage/spack-stage-lvrt51w9/scr-1.2.0/spack-build/examples && /home/idanmos/spack/opt/spack/linux-centos7-x86_64/gcc-4.8.5/cmake-3.11.4-gify4cpe7hrtkaxrvrghwqdsb56zlci4/bin/cmake -E cmake_link_script CMakeFiles/test_ckpt_C.dir/link.txt --verbose=1
/home/idanmos/spack/lib/spack/env/gcc/g++ -O2 -g -DNDEBUG -rdynamic CMakeFiles/test_ckpt_C.dir/test_ckpt.C.o -o test_ckpt_C -Wl,-rpath,/tmp/idanmos/spack-stage/spack-stage-lvrt51w9/scr-1.2.0/spack-build/src:/home/idanmos/spack/opt/spack/linux-centos7-x86_64/gcc-4.8.5/openmpi-3.1.0-wihq6ns5dpzoja3hm5gvzpxijprv7wh7/lib:/home/idanmos/spack/opt/spack/linux-centos7-x86_64/gcc-4.8.5/zlib-1.2.11-64vg6e4evdrlqgx7iicwhu2hs7lv6gpz/lib:/home/idanmos/spack/opt/spack/linux-centos7-x86_64/gcc-4.8.5/dtcmp-1.1.0-z5diekaxgk42rxabqrq6v3hkp2a2g2c6/lib:/home/idanmos/spack/opt/spack/linux-centos7-x86_64/gcc-4.8.5/libyogrt-1.20-6-tcm7yxo23glyoabtxjceah4y3ghzpjx6/lib ../src/libscr.so /home/idanmos/spack/opt/spack/linux-centos7-x86_64/gcc-4.8.5/openmpi-3.1.0-wihq6ns5dpzoja3hm5gvzpxijprv7wh7/lib/libmpi.so /home/idanmos/spack/opt/spack/linux-centos7-x86_64/gcc-4.8.5/zlib-1.2.11-64vg6e4evdrlqgx7iicwhu2hs7lv6gpz/lib/libz.so /home/idanmos/spack/opt/spack/linux-centos7-x86_64/gcc-4.8.5/dtcmp-1.1.0-z5diekaxgk42rxabqrq6v3hkp2a2g2c6/lib/libdtcmp.so /home/idanmos/spack/opt/spack/linux-centos7-x86_64/gcc-4.8.5/libyogrt-1.20-6-tcm7yxo23glyoabtxjceah4y3ghzpjx6/lib/libyogrt.so
CMakeFiles/test_ckpt_C.dir/test_ckpt.C.o: In function `MPI::Op::Init(void (*)(void const*, void*, int, MPI::Datatype const&), bool)':
/home/idanmos/spack/opt/spack/linux-centos7-x86_64/gcc-4.8.5/openmpi-3.1.0-wihq6ns5dpzoja3hm5gvzpxijprv7wh7/include/openmpi/ompi/mpi/cxx/op_inln.h:122: undefined reference to `ompi_mpi_cxx_op_intercept'
CMakeFiles/test_ckpt_C.dir/test_ckpt.C.o: In function `MPI::Intracomm::Create_graph(int, int const*, int const*, bool) const':
/home/idanmos/spack/opt/spack/linux-centos7-x86_64/gcc-4.8.5/openmpi-3.1.0-wihq6ns5dpzoja3hm5gvzpxijprv7wh7/include/openmpi/ompi/mpi/cxx/intracomm.h:25: undefined reference to `MPI::Comm::Comm()'
It seems like Open MPI may have pulled in references to C++ bindings because the app was compiler with a C++ compiler.
Thank you @adammoody @gonsie and @hjelmn for your help. I have no problem compiling for the master branch. And I would also like to try your approach @gonsie. I’ll get to it first thing on sunday. If you have further Insights I would love to hear them.
@gonsie your suggestion worked for me. tough I would like to also be able to install using spack. with a future update that solves this issue. @adammoody I’d love to get an update when such a patch is available. thank’s for your help.
I have 6 failed tests when running make test.
The failed tests are:
- 7:serial_test_api_multiple_start
- 8:serial_test_api_multiple_restart
- 10:parallel_test_api_multiple_start
- 11:parallel_test_api_multiple_restart
You can see LastTest.log here:
LastTest.log
The output of all the failed tests is either a segmentation fault or something like this:
7/36 Testing: serial_test_api_multiple_start
7/36 Test: serial_test_api_multiple_start
Command: "/usr/bin/srun" "-ppbatch" "-t" "5" "-N" "1" "./test_api_multiple"
Directory: /home/idanmos/scr/scr_bld2/examples
"serial_test_api_multiple_start" start time: Jul 09 14:41 IDT
Output:
----------------------------------------------------------
[node023:25507] *** An error occurred in MPI_Type_get_extent
[node023:25507] *** reported by process [350945281,0]
[node023:25507] *** on communicator MPI_COMM_WORLD
[node023:25507] *** MPI_ERR_TYPE: invalid datatype
[node023:25507] *** MPI_ERRORS_ARE_FATAL (processes in this communicator will now abort,
[node023:25507] *** and potentially your MPI job)
SCR v1.2.0: rank 0 on node023.rcl_hpc: Failed to record cluster name @ /home/idanmos/scr/scr/src/scr.c:608
SCR v1.2.0 WARNING: rank 0 on node023.rcl_hpc: Forcing copy type to SINGLE in redundancy descriptor 0 @ /home/idanmos/scr/scr/src/scr_reddesc.c:554
SCR v1.2.0: rank 0 on node023.rcl_hpc: scr_fetch_files: return code 1, 0.000183 secs
Init: Min 0.018966 s Max 0.018966 s Avg 0.018966 s
SCR v1.2.0: rank 0 on node023.rcl_hpc: Starting dataset timestep.1
srun: error: node023: task 0: Exited with exit code 3
<end of output>
Test time = 1.05 sec
----------------------------------------------------------
Test Failed.
"serial_test_api_multiple_start" end time: Jul 09 14:41 IDT
"serial_test_api_multiple_start" time elapsed: 00:00:01
----------------------------------------------------------
I am having a hard time understaning where and why do these tests fail and whether it is connected to the comiplation problem I had and it’s fix.
I would appreciate your help in the manner.
Thanks in advance.
I’ve lost track of the status on this particular issue, but I think it was resolved. I’ll close out this issue since the last PR was merged.
Let’s open up a fresh issue or reopen this one if there is still a problem to be fixed.