AutoLink

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 :

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 :

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 : , 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 : In any deported code that should use AutoLink, include in the following order (* means that it is not always required)

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 :

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

3.2) In case of trouble

Please check the following : 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