How to use AutoLink in your source code
This is related to the use of AutoMap and AutoLink v3.00
The following file will explain how to use AutoMap generated files for AutoLink, and how to generate those files.
Warning : AutoLink requires AutoMap to generate some of its files, you can get both (or use the web version of AutoMap) from the MPI data-type tools home page.
Quick Links :
Main Page |
AutoMap |
AutoLink |
Mailing List |
License |
Award |
Papers |
Acknowledgments
1) Create output files
1.1) Preparing structure file
1.1.1) Rules
To prepare the structure file to be processed by AutoMap, a few rules are to be followed :
- a begin mark
/*~ AM_Begin */
must be placed before the type definitions.
- an end mark
/*~ AM_End */
must be inserted after the type definitions.
- each type that the user want to recognize must have
/*~ AM */
after the typedef declaration, and before the last semi-colon (;) of the line.
- each type referred to by pointer does not have to be AutoMap marked for AutoLink to be processed. If type A uses a pointer reference to type B, but user only want to have control other type A, it is not necessary to AutoMap mark type B.
- each pointer type must be strongly typed; no
void *
can be used for AutoLink.
- no types such as
char *
can be used in data-types, but char element[size]
must be used instead.
- Warning : AutoMap does not work with
struct
alone (using an AutoMap marker), all types must be used as typedef struct
.
1.1.2) Example
The following lines are a very simple example of a possible use of AutoMap to generate AutoMap (MPI data-types) and AutoLink (traversing and recreation of dynamic data-types) output files.
Let's call the following file for future references struct.h
/*~ AM_Begin */
typedef struct {
int a;
char b;
int c;
} intStruct;
struct _Partstruct {
intStruct* test;
int class;
double d[6];
char b[7];
int c[8];
};
typedef struct _Partstruct Partstruct /*~ AM */;
/*~ AM_End */
1.2) Running AutoMap
1.2.1) Concept
You must run AutoMap in the directory where you want the output files to be generated.
To run AutoMap, if it is in your path, simply type the name or your AutoMap executable, otherwise put the full pathname to it, and the name of the executable.
AutoMap options are :
AutoMap [-help] [-v] [-log] [-noAL] filename
-help : Will print this help menu
-v : Verbose mode
-log : Will generate the "logbook.txt" for this run
-noAL : Will not generate the entries for use with AutoLink
filename : name of the C typedef definition file to analyze
When using AutoMap, you may want to have a look at the log file (logbook.txt
) that AutoMap generates when asked to (-log
option); but this is for users who want to understand to the lowest level how AutoMap works. For other users, should they want to follow the processing of AutoMap, it is easy to run it in "verbose" (-v
option) mode, so that you can see if all the data-types you expected are generated.
In the case where you do not want to use AutoLink --for example cases where you do not have pointers to follow, but only basic data-types-- use the "no AutoLink" (-noAL
) option.
The filename is the name of the file containing the data-types to be AutoMap created, formatted as defined in section 1.1.
1.2.2) Example
We run AutoMap on the file "struct.h" defined previously, in verbose mode :
AutoMap -v -log struct.h
, gives us :
Information on this run :
- Will generate AutoLink output files
- Will process file : struct.h
Creating AutoMap log file ... done
Creating the AST ... done
Updating the AST ... done
Writing mpitypes.inc (& mpitypes.h) ... done
Writing al_routines.inc, al_routines.h, autolink.h ... done
--> Generated output for :
----> intStruct (AutoMap and AutoLink subType)
----> Partstruct (userType)
--> done
Cleaning the AST ... done
Closing log file ... done
AutoMap finished without error
Output files can be found in current directory.
AutoMap remarks can be found in the logbook file.
0 Errors, 0 Warnings, Highest Severity 0
, telling us that output for data-types intStruct and Partstruct
have been generated, both for their MPI type creation and AutoLink.
The file generated are :
-
autolink.h
: to specify the prototype of the functions available to the user.
-
al_routines.inc
: to specify internal definitions to AutoLink send and receive functions.
-
al_routines.h
: header file used by some of AutoLink files.
-
mpitypes.inc
: contains the function required to create the MPI data-types.
-
mpitypes.h
: to define functions and types prototypes.
-
logbook.txt
: to store the generation log (only generated because of the -log
option).
2) Use of Output files in user code
2.1) Makefile definition
With AutoLink should come a base Makefile that should help you use AutoMap and AutoLink, should you just take the time to adapt it to your needs (the comments in the Makefile should help you do so).
2.2) Edit user code
2.2.1) Concept
To have AutoLink ready, you should have the following files :
-
al_common.h
-
al_internals.c
-
al_internals.h
-
al_routines.inc
-
al_routines.h
-
autolink.h
-
autolink.inc
-
mpitypes.h
-
mpitypes.inc
, also the user code (here called userprog.c
) and the type definition file (here struct.h
).
The following pictures explains the use of those files :
To be able to use AutoLink, in your main code, please, include in the following order the following files :
-
mpi.h
-
struct.h
-
autolink.inc
In any deported code that should use AutoLink, include in the following order (* means that it is not always required)
-
mpi.h
(*)
-
struct.h
(*)
-
autolink.h
2.2.2) Example
If the main code definition is done in userprog.c
:
#include <mpi.h>
#include "struct.h"
#include "autolink.inc"
, will make AutoLink functions available to user code.
2.3) Use of AutoLink functions
2.3.1) AL_Init(size)
2.3.1.1) Concept
AutoLink uses Packets to fasten transfer of linked elements by sending multiple elements of a same type at once.
Use AL_Init
only in the main definition and after having done MPI_Init
The size parameter is an integer value given in bytes, setting the PacketSize. Note that a negative value will make AutoLink use the default PacketSize set in al_common.h
A 0 size value, will make AutoLink behave as if it had to transfer each element one at a time (only useful to show you the speed up that AutoLink provides --testing shows that AutoLink can improve the transfer of a 20000 elements Linked List from 7 seconds to less than half a second).
2.3.1.2) Example
In file userprog.c
:
MPI_Init(&argc,&argv);
AL_Init(8000); /* Let's use a 8000 bytes PacketSize */
2.3.2) AL_SetPacketSize(size)
2.3.2.1) Concept
Will enable the user to change the maximum size of the packet sent for each data-type, by setting the new size to size bytes. This need to be done for each AutoLink communicating processes.
Note that since AutoLink v2.20, the user can only set PacketSize using AL_Init
. It is forbidden --due to the new internal block data-type-- to dynamically change it. The only case when this is allowed is if the user acknowledge taking full care of possible memory leaks that may be introduced. To enable it, a define (AL_USERCONTROL_PACKET
) has to be set.
Mostly, it is recommanded to only use PacketSize control for PacketSize Tuning.
AL_SetPacketSize
return an integer (AL_True
or AL_False
).
2.3.2.2) Example
In file userprog.c
, after having done the AutoLink initialization :
if (AL_SetPacketSize(8192) == AL_True) {
/* Note that if not allowed, an entry will be added to the log (if allowed) */
2.3.3) AL_Send(buf, datatype, dest, tag, comm)
2.3.3.1) Concept
This function performs a blocking send; it will transfer a dynamic data-type following every --first level-- pointer in the data-type from entry point buf of data-type datatype (defined by AL_ + data-type name) to MPI rank dest with matching tag and communicator. Return MPI_SUCCESS
if no error encountered.
2.3.3.2) Example
In file userprog.c
, should it be an MPI program of 2 nodes, if sending is done from rank 0 to rank 1, and var
being a filled data-type of type Partstruct *
:
[...]
Partstruct *var;
[... filling var]
tag = 0;
next_rank = 1;
if (AL_Send(var, AL_Partstruct, next_rank, tag, MPI_COMM_WORLD)
!= MPI_SUCCESS) {
printf("Error in Sending");
exit(1);
}
2.3.4) AL_Recv(buf, datatype, source, tag, comm, status, rlist)
2.3.4.1) Concept
This function performs a blocking receive; it will receive and reconstruct a data-type sent by AutoLink through the AL_Send
function. It will store the address of the first element of the recreated dynamic data-type into buf (need the address of a pointer), and the data-type of the recreated element in datatype (need the address of a integer variable). This for an element sent from source with matching tag and comm. Plus if given, will store an MPI status into status.
Since AutoLink v2.20, a new parameter can be given; rlist
. This parameter can be :
-
NULL
: in this case, AutoLink will behave like the old version; recreating each element in memory so that users can free
them.
-
AL_ReqList **
: by using this additional argument, users provide a pointer (to a pointer) of AL_ReqList (AutoLink will take care of memory allocation and freeing) so that every AutoLink's special memory block used is recorded. Data-types elements can then no more be freed individually, but all can be freed using the AL_Free
function. Note that since you can reuse the same AL_ReqList
, it is required to set it to NULL when first creating it.
2.3.4.2) Example 1
(Each element is created in memory)
In file userprog.c
, should it be an MPI program of rank 2, if receiving is done on rank 1, and var
being a data-type of type Partstruct *
(not filled, neither malloced).
Partstruct *var;
MPI_Status status;
next_rank = 0;
tag = 0;
if (AL_Recv((void *) &var, &tmp, next_rank, tag, MPI_COMM_WORLD, &status, NULL)
!= MPI_SUCCESS) {/* if */
printf("Error in Receiving");
exit(1);
}
[...]
/* User must free "var" by using free on each element of var */
2.3.4.3) Example 2
(Same example using AL_ReqList)
Partstruct *var;
AL_ReqList *varALfree = NULL;
MPI_Status status;
next_rank = 0;
tag = 0;
if (AL_Recv((void *) &var, &tmp, next_rank, tag, MPI_COMM_WORLD, &status, &varALfree)
!= MPI_SUCCESS) {/* if */
printf("Error in Receiving");
exit(1);
}
[...]
/* Empty var : AL_Recv'd */
AL_Free(&varALfree);
2.3.5) AL_ISend(buf, datatype, dest, tag, comm, rqlist)
2.3.5.1) Concept
This function performs a --standard mode,-- non-blocking send; it uses the same arguments than defined in AL_Send
with the addition of rqlist
, which is the AutoLink special request handle, that you will need to perform further operations on a specific request.
2.3.5.2) Example
This uses the same example as defined for the AL_Send
function, applied to an AL_ISend
operation :
[...]
Partstruct *var;
AL_ISendRL *rqlist;
[... filling var]
tag = 0;
next_rank = 1;
if (AL_ISend(var, AL_Partstruct, next_rank, tag, MPI_COMM_WORLD, &rqlist)
!= MPI_SUCCESS) {
printf("Error in Sending");
exit(1);
}
2.3.6) AL_ISendTest(rqlist)
2.3.6.1) Concept
This function tests the send requests, to see if they are completed, and return at once. It returns MPI_SUCCESS
if all messages are sent.
This operation does not complete the AL_ISend
operation.
2.3.6.2) Example
This is a continuation of the example presented for the AL_ISend
function :
[... AL_ISend]
printf("Rank %d : AL_ISendTest completion ?\n", my_rank);
if (AL_ISendTest(&rqlist) != MPI_SUCCESS)
printf("Rank %d : Send not completed\n", my_rank);
else
printf("Rank %d : Send completed\n", my_rank);
2.3.7) AL_ISendWait(rqlist)
2.3.7.1) Concept
This function waits until all the send requests are complete. It returns MPI_SUCCESS
if all messages are sent.
This operation does not complete the AL_ISend
operation.
2.3.7.2) Example
This is a continuation of the example presented for the AL_ISend
function :
[... AL_ISend]
printf("Rank %d : AL_ISendWait\n", my_rank);
if (AL_ISendWait(&rqlist) != MPI_SUCCESS) {
printf("Rank %d : Error in Waiting\n");
exit(1);
}
2.3.8) AL_ISendComplete(rqlist)
2.3.8.1) Concept
This function completes all pending send requests for the specified rqlist
. It returns MPI_SUCCESS
if no error occured.
This operation does complete the AL_ISend
operation.
2.3.7.2) Example
This is the conclusion of the example presented for the AL_ISend
function :
[... AL_ISend]
printf("Rank %d : AL_ISendComplete\n", my_rank);
if (AL_ISendComplete(&rqlist) != MPI_SUCCESS) {
printf("Rank %d : Error in Completion\n");
exit(1);
}
2.3.9) AL_IRecv(buf, datatype, source, tag, comm, rqlist, rlist)
2.3.9.1) Concept
This function performs a --standard mode,-- non-blocking receive, the arguments and use of this function is the same that for AL_Send
except for the replacement of status
by rqlist
which is the AutoLink special request handle, that you will need to perform further operations on a specific request.
2.3.9.2) Example
This is a reproduction of the example presented for AL_Recv
(in the case where "each element is created in memory") :
Partstruct *var;
AL_IRecvRL *rqlist;
next_rank = 0;
tag = 0;
if (AL_IRecv((void *) &var, &tmp, next_rank, tag, MPI_COMM_WORLD, &rqlist, NULL)
!= MPI_SUCCESS) {/* if */
printf("Error in Receiving");
exit(1);
}
[...]
/* User must free "var" by using free on each element of var */
2.3.10) AL_IRecvTest(rqlist)
2.3.10.1) Concept
This function tests the receive requests, to see if they are completed, and return at once. It returns MPI_SUCCESS
if all messages are received.
This operation does not complete the AL_IRecv
operation.
2.3.10.2) Example
This is a continuation of the example presented for the AL_IRecv
function :
[... AL_IRecv]
printf("Rank %d : AL_IRecvTest completion ?\n", my_rank);
if (AL_IRecvTest(&rqlist) != MPI_SUCCESS)
printf("Rank %d : Recv not completed\n", my_rank);
else
printf("Rank %d : Recv completed\n", my_rank);
2.3.11) AL_IRecvWait(rqlist)
2.3.11.1) Concept
This function waits until all the receive requests are complete. It returns MPI_SUCCESS
if all messages are received.
This operation does not complete the AL_ISend
operation.
2.3.11.2) Example
This is a continuation of the example presented for the AL_IRecv
function :
[... AL_IRecv]
printf("Rank %d : AL_IRecvWait\n", my_rank);
if (AL_IRecvWait(&rqlist) != MPI_SUCCESS) {
printf("Rank %d : Error in Waiting\n");
exit(1);
}
2.3.12) AL_IRecvComplete(rqlist)
2.3.12.1) Concept
This function completes all pending receive requests for the specified rqlist
, and the start the link reconstruction and memory reconstruction according to the rlist
specification used for the corresponding AL_IRecv
function. It returns MPI_SUCCESS
if no error occured.
This operation does complete the AL_IRecv
operation.
2.3.12.2) Example
This is the conclusion of the example presented for the AL_IRecv
function :
[... AL_IRecv]
printf("Rank %d : AL_IRecvComplete\n", my_rank);
if (AL_IRecvComplete(&rqlist) != MPI_SUCCESS) {
printf("Rank %d : Error in Completion\n");
exit(1);
}
2.3.13) AL_Finalize()
2.3.13.1) Concept
Finalizing AutoLink is to be done before MPI_Finalize
.
2.3.13.2) Example
In userprog.c
;
AL_Finalize();
MPI_Finalize();
2.3.14) AL_LogEntry(entry)
2.3.14.1) Concept
Add a user entry to the AutoLink "benchmark log". Requires the _AL_DBG_UBENCH
define to add entries. AutoLink extractor script (al_bench.pl
) will get the time and packet size before the user data. It is an easy way for the user to generate additional entries for special benchmarking by formatting the printed entries.
2.3.14.2) Example
In userprog.c
;
#include <string.h>
[...]
char stmp[80];
[...]
sprintf(stmp, "%d \t%f # %s\n",iteration, value, comment);
AL_LogEntry(stmp);
, will add in the log an entry with the iteration number, the value followed by a # and a comment text. Such an example can be used in a data visualization tool like "gnuplot", giving a third and fourth column to work with and a comment on which the user can always "grep" in order to extract special data.
2.3.14) AL_Free(rlist)
This function is here to delete every element created by AutoLink using AL_Recv
or AL_IRecv
and using a rlist
.
2.3.14.2) Example
See AL_Recv
for an example of use.
2.4) Running code
After compiling code (see the basic Makefile given), you should be able to try it and enjoy the high level functions provided by AutoLink to you.
3) Troubleshooting & Known problems
3.1) Special note for non-blocking operations
- Communicator : As for any MPI parallel library, it is recommended to use a special communicator with AutoLink functions. AutoLink however ,does not create any additional communicator, it rather uses the user specified one.
- Tag : It is recommended to use special tags for AutoLink non-blocking operations and not use them for any other MPI functions. This is due to the fact that functions performed are not local (AutoLink schedules the way it transfers data-types).
- MPI : We have encountered some strange behavior with different implementations of MPI during the stress test of the library,, but we were able to isolate the problem as some MPI implementation bug. Should you encounter some kind of deadlocking, if you could send a bug report to martial.michel@nist.gov, with a complete log, if possible your source code and the information on the MPI library used, it will prove of great help.
3.2) In case of trouble
Please check the following :
- You did not forget the begin (
/*~ AM_Begin */
) and end (/*~ AM_End */
) marker, before and after the type definitions.
- You did use the AutoMap type marker (
/*~ AM */
) on the type you desire to work with.
- You did not use the AutoMap type marker on a struct alone.
- You used the proper options when launching AutoMap
- You included the proper file.
- You used AutoLink functions, as defined in the examples.
Should you encounter another problem, please, set a trace mode for AutoMap creation and/or AutoLink. Add to it your type definition file, command lines, and a small example of how you use AutoMap and AutoLink to martial.michel@nist.gov with [ALpb]
in the subject.
Page created : 1997
Last update : 26 Oct 2001
By> : SAVG