next up previous contents
Next: Опции mpirun Up: Автоматическая генерация профилирующих библиотек Previous: Автоматическая генерация профилирующих библиотек   Contents

Написание определения обрамления

Определения обрамления сами по себе состоят из кода на С со специальными макросами. Каждый макрос окружен последовательностью $\lbrace$$\lbrace$$\rbrace$$\rbrace$. Следующий макрос распознается wrappergen:
$\lbrace$$\lbrace$ fileno$\rbrace$$\rbrace$
Целочисленный индекс представляет, из какого файла обрамления происходит макрос. Это полезно при описании глобальных для файла переменных, чтобы избежать пересечения имен. Рекомендуется, чтобы все идентификаторы, описанные вне функций, оканчивались на _$\lbrace$$\lbrace$ fileno$\rbrace$$\rbrace$. Например:
static double overhead_time_$\lbrace$$\lbrace$ fileno$\rbrace$$\rbrace$;
может расширяться до:
static double overhead_time_0;
(конец примера).

$\lbrace$$\lbrace$ forallfn <function name escape> <функция A> <функция B> ... $\rbrace$$\rbrace$
...
$\lbrace$$\lbrace$endforallfn$\rbrace$$\rbrace$

Код между $\lbrace$$\lbrace$ forallfn$\rbrace$$\rbrace$ и $\lbrace$$\lbrace$endforallfn$\rbrace$$\rbrace$ копируется один раз для каждой профилируемой функции, исключая перечисленные функции, заменяя <function name escape> именем каждой из функций. Например:
$\lbrace$$\lbrace$forallfn fn_name$\rbrace$$\rbrace$ static int $\lbrace$$\lbrace$fn_name$\rbrace$$\rbrace$_ncalls_$\lbrace$$\lbrace$fileno$\rbrace$$\rbrace$;
$\lbrace$$\lbrace$endforallfn$\rbrace$$\rbrace$
может расширяться до:
static int MPI_Send_ncalls_1;
static int MPI_Recv_ncalls_1;
static int MPI_Bcast_ncalls_1;
(конец примера).

$\lbrace$$\lbrace$foreachfn <function name escape> <функция A> <функция B> ... $\rbrace$$\rbrace$
...
$\lbrace$$\lbrace$endforeachfn$\rbrace$$\rbrace$

$\lbrace$$\lbrace$foreachfn$\rbrace$$\rbrace$ - это то же самое, что и $\lbrace$$\lbrace$forallfn$\rbrace$$\rbrace$, за исключением того, что обрамления будут написаны только для точно названных функций. Например:
$\lbrace$$\lbrace$forallfn fn_name mpi_send mpi_recv$\rbrace$$\rbrace$static int $\lbrace$$\lbrace$fn_name$\rbrace$$\rbrace$_ncalls_$\lbrace$$\lbrace$fileno$\rbrace$$\rbrace$;
$\lbrace$$\lbrace$endforallfn$\rbrace$$\rbrace$
может расширяться до:
static int MPI_Send_ncalls_2;
static int MPI_Recv_ncalls_2;
(конец примера).

$\lbrace$$\lbrace$fnall <function name escape> <функция A> <функция B> ... $\rbrace$$\rbrace$
...
$\lbrace$$\lbrace$callfn$\rbrace$$\rbrace$ ...$\lbrace$$\lbrace$endfnall$\rbrace$$\rbrace$

$\lbrace$$\lbrace$fnall$\rbrace$$\rbrace$ определяет обрамление, используемое для всех функций, исключая названные.
wrappergen расширяет их в полное определение функции в традиционном формате С. Макрос $\lbrace$$\lbrace$callfn$\rbrace$$\rbrace$ сообщает wrappergen, где вставить вызов функции, которая будет профилироваться. Должен быть только один экземпляр макроса $\lbrace$$\lbrace$callfn$\rbrace$$\rbrace$ в каждом определении оболочки. Макрос, определенный <function name escape> заменяется именем каждой из функций.

Внутри определения обрамления распознаются другие макросы.

$\lbrace$$\lbrace$vardecl <type> <arg> <arg> ... $\rbrace$$\rbrace$
Используйте vardecl для объявления переменных внутри определения обрамления. Если вложенный макрос требует переменных, заданных посредством vardecl с теми же именами, wrappergen создаст уникальные имена добавлением последовательных целых в конец требуемого имени (var, var1, var2, ...), пока не будет создано уникальное имя. Неразумно объявлять переменные в определении обрамления вручную, поскольку имена переменных могут конфликтовать с другими обрамлениями, а определения переменных могут встретиться в коде позже, чем выражения из других обрамлений, что запрещено в классическом и ANSI C.
$\lbrace$$\lbrace$<varname>$\rbrace$$\rbrace$
Если переменная описана через vardecl, то требуемое имя для этой переменной (которое может отличаться от унифицированной формы, которая появится в финальном коде) становится временным макросом, который будет расширен в унифицированную форму. Например,
$\lbrace$$\lbrace$vardecl int id$\rbrace$$\rbrace$
может расширяться до:
int i, d3;
(конец примера)
$\lbrace$$\lbrace$<argname>$\rbrace$$\rbrace$
Рекомендуемый, но не необходимый макрос, состоящий из имени одного из аргументов профилируемой функции, расширяется до имени соответствующего аргумента. Этот макрос служит небольшой цели, иной чем вставка, чтобы профилируемая функция имела аргумент с заданным именем.
$\lbrace$$\lbrace$<argnum>$\rbrace$$\rbrace$
Аргументы профилируемой функции могут также адресоваться увеливающимся номером, начиная с 0.
$\lbrace$$\lbrace$returnVal$\rbrace$$\rbrace$
returnVal расширяется до переменной, используемой для хранения возвращаемого результата профилируемой функции.
$\lbrace$$\lbrace$callfn$\rbrace$$\rbrace$
callfn расширяется до вызова профилируемой функции. При вложенных определениях обрамления, это также представляет точку для вставки кода любой вложенной внутренней функции. Порядок вложенности определяется порядком, в котором встречаются обрамления программе wrappergen. Например, если два файла `prof1.w' и `prof2.w' каждый содержат два обрамления для MPI_Send, профилированный код, созданный с использованием обоих файлов, имеет вид:
int MPI_Send ( аргументы...)
объявление аргументов...
$\lbrace$
/*код перед вызовом функции из обрамления 1 из prof1.w */
/*код перед вызовом функции из обрамления 2 из prof1.w */
/*код перед вызовом функции из обрамления 1 из prof2.w */
/*код перед вызовом функции из обрамления 2 из prof2.w */
returnVal = MPI_Send ( аргументы... );
/*код после вызова функции из обрамления 2 из prof2.w */
/*код после вызова функции из обрамления 1 из prof2.w */
/*код после вызова функции из обрамления 2 из prof1.w */
/*код после вызова функции из обрамления 1 из prof1.w */
return returnVal;
$\rbrace$

$\lbrace$$\lbrace$fn <function name escape> <function A> <function B> ... $\rbrace$$\rbrace$
...
$\lbrace$$\lbrace$callfn$\rbrace$$\rbrace$
...
$\lbrace$$\lbrace$endfnall$\rbrace$$\rbrace$

fn идентично fnall, за исключением генерации обрамлений только для точно названных функций. Например:
$\lbrace$$\lbrace$fn this_fn MPI_Send$\rbrace$$\rbrace$
$\lbrace$$\lbrace$vardecl int i$\rbrace$$\rbrace$
$\lbrace$$\lbrace$callfn$\rbrace$$\rbrace$
printf ( ``Вызов $\lbrace$$\lbrace$this_fn$\rbrace$$\rbrace$.$\backslash$n'' );
printf ( ``$\lbrace$$\lbrace$i$\rbrace$$\rbrace$ не используется.$\backslash$n'' );
printf ( ``Первый аргумент для $\lbrace$$\lbrace$this_fn$\rbrace$$\rbrace$ это $\lbrace$$\lbrace$0$\rbrace$$\rbrace$$\backslash$n'' );
$\lbrace$$\lbrace$endfn$\rbrace$$\rbrace$
будет расширен до:
int MPI_Send (buf, count, datatype, dest, tag, comm )
void * buf;
int count;
MPI_Datatype datatype;
int dest;
int tag;
MPI_Comm comm;
$\lbrace$
int returnVal;
int i;
returnVal = PMPI_Send ( buf, count, datatype, dest, tag, comm );
printf ( "Вызов MPI_Send.$\backslash$n" );
printf ( "i не используется.$\backslash$n" );
printf ( "Первый аргумент для MPI_Send это buf$\backslash$n" );
return returnVal;
$\rbrace$

$\lbrace$$\lbrace$fn_num$\rbrace$$\rbrace$

Это номер, начинающийся с 0. Он наращивается при каждом использовании.
Простой файл обрамления находится в `sample.w', а соответствующий вывод в `sample.out'.
next up previous contents
Next: Опции mpirun Up: Автоматическая генерация профилирующих библиотек Previous: Автоматическая генерация профилирующих библиотек   Contents
Alex Otwagin 2002-12-16