Skip to content

Instantly share code, notes, and snippets.

@bosilca
Last active August 29, 2015 14:14
Show Gist options
  • Save bosilca/1716cbc1e71a3dd0baf4 to your computer and use it in GitHub Desktop.
Save bosilca/1716cbc1e71a3dd0baf4 to your computer and use it in GitHub Desktop.
Index: datatypes.tex
===================================================================
--- datatypes.tex (revision 1835)
+++ datatypes.tex (working copy)
@@ -128,6 +128,7 @@
lb(Typemap) & = & \min_j disp_j , \nonumber \\
ub(Typemap) & = & \max_j (disp_j + \mpicode{sizeof}(type_j)) + \epsilon , \mbox{ and}
\nonumber \\ extent(Typemap) & = & ub(Typemap) - lb(Typemap).
+\label{soft-lb-ub-definition}
\end{eqnarray}
If $type_j$ requires alignment to a byte address that
is
@@ -141,7 +142,7 @@
\ftype{BIND(C)} derived types,
or derived types that are neither \ftype{SEQUENCE} nor \ftype{BIND(C)}.
The complete definition of \mpiterm{extent} is given
-in \sectionref{subsec:pt2pt-markers}.
+by Equation~\ref{soft-lb-ub-definition} \sectionref{sec:pt2pt-datatype}.
\begin{example}
@@ -1311,11 +1312,30 @@
specify the absolute address of the entries in the communication
buffer, in which case the \mpiarg{buf} argument is passed the value
\const{MPI\_BOTTOM}.
+Note that in Fortran \consti{MPI\_BOTTOM} is not usable for initialization or
+assignment, see Section~\ref{subsec:named-constants}.
The address of a location in memory can be found by invoking the
function\flushline
\mpifunc{MPI\_GET\_ADDRESS}.
+The relative displacement between two absolute addresses
+can be calculated with the function \mpifunc{MPI\_AINT\_DIFF}. A new absolute
+address as sum of an absolute base address and a relative displacement can be
+calculated with the function \mpifunc{MPI\_AINT\_ADD}. To ensure portability,
+arithmetic on absolute addresses should not be performed with the intrinsic
+operators ``-'' and ``+''. See also Sections \ref{subsec:displacement} and
+\ref{subsec:pt2pt-segmented} on pages \pageref{subsec:displacement} and
+\pageref{subsec:pt2pt-segmented}.
+
+\begin{rationale}
+Address sized integer values, i.e., \type{MPI\_Aint} or
+\ftype{INTEGER(KIND=MPI\_ADDRESS\_KIND)} values, are signed integers, while
+absolute addresses are unsigned quantities. Direct arithmetic on addresses
+stored in address sized signed variables can cause overflows, resulting in
+undefined behavior.
+\end{rationale}
+
\begin{funcdef}{MPI\_GET\_ADDRESS(location, address)}
\funcarg{\IN}{location}{location in caller memory (choice)}
\funcarg{\OUT}{address}{address of location (integer)}
@@ -1331,17 +1351,6 @@
Returns the (byte) address of \mpiarg{location}.
-\begin{users}
-Current Fortran \MPI/ codes will run unmodified, and will port to any
-system. However, they may fail if addresses larger than $2^{32} -1$
-are used in the program. New codes should be written so that they use
-the new functions. This provides compatibility
-with C/C++ and avoids errors on 64 bit architectures. However, such
-newly written codes may need to be (slightly) rewritten to port to old
-Fortran 77 environments that do not support \constskip{KIND}
-declarations.
-\end{users}
-
\begin{rationale}
In the \code{mpi\_f08} module, the \mpiarg{location} argument is not defined
with \ftype{INTENT(IN)} because existing applications may use
@@ -1364,7 +1373,7 @@
INTEGER(KIND=MPI_ADDRESS_KIND) I1, I2, DIFF
CALL MPI_GET_ADDRESS(A(1,1), I1, IERROR)
CALL MPI_GET_ADDRESS(A(10,10), I2, IERROR)
- DIFF = I2 - I1
+ DIFF = MPI_AINT_DIFF(I2, I1)
! The value of DIFF is 909*sizeofreal; the values of I1 and I2 are
! implementation dependent.
\end{verbatim}
@@ -1408,6 +1417,62 @@
%% ``{\sf Temporary Data Movements}'' and ``{\sf Permanent Data Movements}''.
\end{users}
+To ensure portability, arithmetic on MPI addresses must be
+performed using the \mpifunc{MPI\_AINT\_ADD}
+and \mpifunc{MPI\_AINT\_DIFF} functions.
+
+\begin{funcdef}{MPI\_AINT\_ADD(base, disp)}
+\funcarg{\IN}{base}{base address (integer)}
+\funcarg{\IN}{disp}{displacement (integer)}
+\end{funcdef}
+
+\cdeclindex{MPI\_Aint}%
+\mpibindnotint{MPI\_Aint MPI\_Aint\_add(MPI\_Aint base, MPI\_Aint disp)}
+
+\mpifnewbind{INTEGER(KIND=MPI\_ADDRESS\_KIND) MPI\_Aint\_add(base, disp) \fargs INTEGER(KIND=MPI\_ADDRESS\_KIND), INTENT(IN) :: base, disp}
+\mpifbind{INTEGER(KIND=MPI\_ADDRESS\_KIND) MPI\_AINT\_ADD(BASE, DISP) \fargs INTEGER(KIND=MPI\_ADDRESS\_KIND) BASE, DISP}
+
+\mpifunc{MPI\_AINT\_ADD} produces a new \consti{MPI\_Aint} value that is
+equivalent to the sum of the \mpiarg{base} and \mpiarg{disp} arguments, where
+\mpiarg{base} represents a base address returned by a call to
+\mpifunc{MPI\_GET\_ADDRESS} and \mpiarg{disp} represents a signed integer
+displacement. The resulting address is valid only at the process that generated
+\mpiarg{base}, and it must correspond to a location in the same object
+referenced by \mpiarg{base}, as described in
+Section~\ref{subsec:pt2pt-segmented}. The addition is performed in a manner
+that results in the correct \consti{MPI\_Aint} representation of the output
+address, as if the process that originally produced \mpiarg{base} had called:
+
+\begin{verbatim}
+MPI_Get_address((char *) base + disp, &result)
+\end{verbatim}
+
+\begin{funcdef}{MPI\_AINT\_DIFF(addr1, addr2)}
+\funcarg{\IN}{addr1}{minuend address (integer)}
+\funcarg{\IN}{addr2}{subtrahend address (integer)}
+\end{funcdef}
+
+\cdeclindex{MPI\_Aint}%
+\mpibindnotint{MPI\_Aint MPI\_Aint\_diff(MPI\_Aint addr1, MPI\_Aint addr2)}
+
+\mpifnewbind{INTEGER(KIND=MPI\_ADDRESS\_KIND) MPI\_Aint\_diff(addr1, addr2) \fargs INTEGER(KIND=MPI\_ADDRESS\_KIND), INTENT(IN) :: addr1, addr2}
+\mpifbind{INTEGER(KIND=MPI\_ADDRESS\_KIND) MPI\_AINT\_DIFF(ADDR1, ADDR2) \fargs INTEGER(KIND=MPI\_ADDRESS\_KIND) ADDR1, ADDR2}
+
+\mpifunc{MPI\_AINT\_DIFF} produces a new \consti{MPI\_Aint} value that is
+equivalent to the difference between \mpiarg{addr1} and \mpiarg{addr2}
+arguments, where \mpiarg{addr1} and \mpiarg{addr2} represent addresses returned
+by calls to \mpifunc{MPI\_GET\_ADDRESS}. The resulting address is valid only
+at the process that generated \mpiarg{addr1} and \mpiarg{addr2}, and
+\mpiarg{addr1} and \mpiarg{addr2} must correspond to locations in the same
+object in the same process, as described in
+Section~\ref{subsec:pt2pt-segmented}. The difference is calculated in a manner
+that results the signed difference from \mpiarg{addr1} to \mpiarg{addr2}, as if
+the process that originally produced the addresses had called
+%
+\verb#(char *) addr1 - (char *) addr2#
+%
+on the addresses initially passed to \mpifunc{MPI\_GET\_ADDRESS}.
+
The following auxiliary functions provide useful information on
derived datatypes.
@@ -1640,7 +1705,7 @@
Returns the lower bound and the extent of
\mpiarg{datatype}
-(as defined in \sectionref{subsec:pt2pt-markers}).
+(as defined in Equation \ref{soft-lb-ub-definition} page \pageref{soft-lb-ub-definition}).
For both functions, if either \OUT\ parameter cannot express the value
to be returned (e.g., if the parameter is too small to hold the output
@@ -2947,7 +3012,7 @@
MPI_Get_address(particle[0].d, disp+1);
MPI_Get_address(particle[0].b, disp+2);
base = disp[0];
-for (i=0; i < 3; i++) disp[i] -= base;
+for (i=0; i < 3; i++) disp[i] = MPI_Aint_diff(disp[i], base);
MPI_Type_create_struct(3, blocklen, disp, type, &Particlestruct);
@@ -2957,7 +3022,7 @@
/* compute extent of the structure */
MPI_Get_address(particle+1, &sizeofentry);
-sizeofentry -= base;
+sizeofentry = MPI_Aint_diff(sizeofentry, base);
/* build datatype describing structure */
@@ -3179,7 +3244,7 @@
MPI_Get_address(u, &i);
MPI_Get_address(u+1, &extent);
-extent -= i;
+extent = MPI_Aint_diff(extent, i);
MPI_Type_create_resized(MPI_INT, 0, extent, &mpi_utype[0]);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment