Целочисленный индекс представляет, из какого файла обрамления происходит макрос. Это полезно при описании глобальных для файла переменных, чтобы избежать пересечения имен. Рекомендуется, чтобы все идентификаторы, описанные вне функций, оканчивались на _ fileno. Например:static double overhead_time_ fileno;может расширяться до:static double overhead_time_0;(конец примера).
forallfn <function name escape> <функция A>
<функция B> ...
...
endforallfn
Код между forallfn и endforallfn копируется один раз для каждой профилируемой функции, исключая перечисленные функции, заменяя <function name escape> именем каждой из функций. Например:forallfn fn_name static int fn_name_ncalls_fileno;может расширяться до:
endforallfnstatic int MPI_Send_ncalls_1;(конец примера).
static int MPI_Recv_ncalls_1;
static int MPI_Bcast_ncalls_1;
foreachfn <function name escape> <функция A>
<функция B> ...
...
endforeachfn
foreachfn - это то же самое, что и forallfn, за исключением того, что обрамления будут написаны только для точно названных функций. Например:forallfn fn_name mpi_send mpi_recvstatic int fn_name_ncalls_fileno;может расширяться до:
endforallfnstatic int MPI_Send_ncalls_2;(конец примера).
static int MPI_Recv_ncalls_2;
fnall <function name escape> <функция A>
<функция B> ...
...
callfn
...endfnall
fnall определяет обрамление, используемое для всех функций, исключая названные.
wrappergen расширяет их в полное определение функции в традиционном формате С. Макрос callfn сообщает wrappergen, где вставить вызов функции, которая будет профилироваться. Должен быть только один экземпляр макроса callfn в каждом определении оболочки. Макрос, определенный <function name escape> заменяется именем каждой из функций.
Внутри определения обрамления распознаются другие макросы.
vardecl <type> <arg> <arg> ...callfnИспользуйте vardecl для объявления переменных внутри определения обрамления. Если вложенный макрос требует переменных, заданных посредством vardecl с теми же именами, wrappergen создаст уникальные имена добавлением последовательных целых в конец требуемого имени (var, var1, var2, ...), пока не будет создано уникальное имя. Неразумно объявлять переменные в определении обрамления вручную, поскольку имена переменных могут конфликтовать с другими обрамлениями, а определения переменных могут встретиться в коде позже, чем выражения из других обрамлений, что запрещено в классическом и ANSI C.<varname>Если переменная описана через vardecl, то требуемое имя для этой переменной (которое может отличаться от унифицированной формы, которая появится в финальном коде) становится временным макросом, который будет расширен в унифицированную форму. Например,<argname>vardecl int idможет расширяться до:int i, d3;(конец примера)Рекомендуемый, но не необходимый макрос, состоящий из имени одного из аргументов профилируемой функции, расширяется до имени соответствующего аргумента. Этот макрос служит небольшой цели, иной чем вставка, чтобы профилируемая функция имела аргумент с заданным именем.<argnum>Аргументы профилируемой функции могут также адресоваться увеливающимся номером, начиная с 0.returnValreturnVal расширяется до переменной, используемой для хранения возвращаемого результата профилируемой функции.
callfn расширяется до вызова профилируемой функции. При вложенных определениях обрамления, это также представляет точку для вставки кода любой вложенной внутренней функции. Порядок вложенности определяется порядком, в котором встречаются обрамления программе wrappergen. Например, если два файла `prof1.w' и `prof2.w' каждый содержат два обрамления для MPI_Send, профилированный код, созданный с использованием обоих файлов, имеет вид:int MPI_Send ( аргументы...)
объявление аргументов...
/*код перед вызовом функции из обрамления 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;
fn <function name escape> <function A> <function
B> ...
...
callfn
...
endfnall
fn идентично fnall, за исключением генерации обрамлений только для точно названных функций. Например:fn this_fn MPI_Sendбудет расширен до:
vardecl int i
callfn
printf ( ``Вызов this_fn.n'' );
printf ( ``i не используется.n'' );
printf ( ``Первый аргумент для this_fn это 0n'' );
endfnint MPI_Send (buf, count, datatype, dest, tag, comm )
void * buf;
int count;
MPI_Datatype datatype;
int dest;
int tag;
MPI_Comm comm;
int returnVal;
int i;
returnVal = PMPI_Send ( buf, count, datatype, dest, tag, comm );
printf ( "Вызов MPI_Send.n" );
printf ( "i не используется.n" );
printf ( "Первый аргумент для MPI_Send это bufn" );
return returnVal;
fn_num
Это номер, начинающийся с 0. Он наращивается при каждом использовании.Простой файл обрамления находится в `sample.w', а соответствующий вывод в `sample.out'.