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