Skip to content

Commit

Permalink
Merge pull request E3SM-Project#147 from mwarusz/mwarusz/omega/real-p…
Browse files Browse the repository at this point in the history
…recision

Enable building and testing Omega in single precision
  • Loading branch information
sbrus89 authored Nov 6, 2024
2 parents 5d6af46 + 9b403ad commit 801ceaa
Show file tree
Hide file tree
Showing 21 changed files with 461 additions and 499 deletions.
2 changes: 1 addition & 1 deletion components/omega/doc/devGuide/DataTypes.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ integer and floating point variables. Note that these exist in the
Omega namespace so use the scoped form OMEGA::I4, etc.
In addition, we define a Real data type that is, by default,
double precision (8 bytes/64-bit) but if the code is built with a
`-DSINGLE_PRECISION` (see insert link to build system) preprocessor flag,
`-DOMEGA_SINGLE_PRECISION` (see insert link to build system) preprocessor flag,
the default Real becomes single precision (4-byte/32-bit). For floating
point variables, developers should use this Real type instead of the
specific R4 or R8 forms unless the specific form is required
Expand Down
2 changes: 1 addition & 1 deletion components/omega/doc/userGuide/DataTypes.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ types to guarantee a specific level of precision. There is only one
user-configurable option for precision. When a specific floating point
precision is not required, we use a Real data type that is, by default,
double precision (8 bytes/64-bit) but if the code is built with a
`-DSINGLE_PRECISION` (see insert link to build system) preprocessor flag,
`-DOMEGA_SINGLE_PRECISION` (see insert link to build system) preprocessor flag,
the default Real becomes single precision (4-byte/32-bit). Users are
encouraged to use the default double precision unless exploring the
performance or accuracy characteristics of single precision.
28 changes: 28 additions & 0 deletions components/omega/src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,14 @@ target_compile_definitions(
OMEGA_ARCH=${OMEGA_ARCH}
)

if(OMEGA_SINGLE_PRECISION)
target_compile_definitions(
OmegaLibFlags
INTERFACE
OMEGA_SINGLE_PRECISION=1
)
endif()

target_link_options(
OmegaLibFlags
INTERFACE
Expand Down Expand Up @@ -57,6 +65,26 @@ target_link_libraries(
OmegaLibFlags
)

# some tests require single precision version of the library
# if OmegaLib is configured to use double precision we need to
# build another version
if(OMEGA_BUILD_TEST AND NOT OMEGA_SINGLE_PRECISION)
add_library(${OMEGA_LIB_NAME}_SP ${_LIBSRC_FILES})

target_link_libraries(
${OMEGA_LIB_NAME}_SP
PRIVATE
OmegaLibFlags
)

target_compile_definitions(
${OMEGA_LIB_NAME}_SP
PUBLIC
OMEGA_SINGLE_PRECISION=1
)
endif()


# build Omega executable
if(OMEGA_BUILD_EXECUTABLE)

Expand Down
2 changes: 1 addition & 1 deletion components/omega/src/base/DataTypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ using R4 = float; ///< alias for 32-bit (single prec) real
using R8 = double; ///< alias for 64-bit (double prec) real

/// generic real 64-bit (default) or 32-bit (if -DSINGLE_PRECISION used)
#ifdef SINGLE_PRECISION
#ifdef OMEGA_SINGLE_PRECISION
using Real = float;
#else
using Real = double;
Expand Down
24 changes: 12 additions & 12 deletions components/omega/src/base/Halo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -647,7 +647,7 @@ int Halo::startReceives() {
I4 BufferSize = TotSize * MyNeighbor->RecvLists[MyElem].NTot;
MyNeighbor->RecvBuffer.resize(BufferSize);
IErr[INghbr] = MPI_Irecv(&MyNeighbor->RecvBuffer[0], BufferSize,
MPI_RealKind, MyNeighbor->TaskID, MPI_ANY_TAG,
MPI_DOUBLE, MyNeighbor->TaskID, MPI_ANY_TAG,
MyComm, &MyNeighbor->RReq);
if (IErr[INghbr] != 0) {
LOG_ERROR("MPI error {} on task {} receive from task {}",
Expand Down Expand Up @@ -676,7 +676,7 @@ int Halo::startSends() {
MyNeighbor = &Neighbors[INghbr];
I4 BufferSize = TotSize * MyNeighbor->SendLists[MyElem].NTot;
IErr[INghbr] =
MPI_Isend(&MyNeighbor->SendBuffer[0], BufferSize, MPI_RealKind,
MPI_Isend(&MyNeighbor->SendBuffer[0], BufferSize, MPI_DOUBLE,
MyNeighbor->TaskID, 0, MyComm, &MyNeighbor->SReq);
if (IErr[INghbr] != 0) {
LOG_ERROR("MPI error {} on task {} send to task {}", IErr[INghbr],
Expand Down Expand Up @@ -709,7 +709,7 @@ int Halo::packBuffer(const HostArray1DI4 Array) {
for (int IExch = 0; IExch < MyList->NList[ILayer]; ++IExch) {
I4 IBuff = MyList->Offsets[ILayer] + IExch;
MyNeighbor->SendBuffer[IBuff] =
reinterpret_cast<Real &>(Array(MyList->Ind[ILayer][IExch]));
reinterpret_cast<R8 &>(Array(MyList->Ind[ILayer][IExch]));
}
}

Expand All @@ -726,7 +726,7 @@ int Halo::packBuffer(const HostArray1DI8 Array) {
for (int IExch = 0; IExch < MyList->NList[ILayer]; ++IExch) {
I4 IBuff = MyList->Offsets[ILayer] + IExch;
MyNeighbor->SendBuffer[IBuff] =
reinterpret_cast<Real &>(Array(MyList->Ind[ILayer][IExch]));
reinterpret_cast<R8 &>(Array(MyList->Ind[ILayer][IExch]));
}
}

Expand Down Expand Up @@ -777,7 +777,7 @@ int Halo::packBuffer(const HostArray2DI4 Array) {
for (int J = 0; J < NJ; ++J) {
I4 IBuff = (MyList->Offsets[ILayer] + IExch) * NJ + J;
MyNeighbor->SendBuffer[IBuff] =
reinterpret_cast<Real &>(Array(MyList->Ind[ILayer][IExch], J));
reinterpret_cast<R8 &>(Array(MyList->Ind[ILayer][IExch], J));
}
}
}
Expand All @@ -797,7 +797,7 @@ int Halo::packBuffer(const HostArray2DI8 Array) {
for (int J = 0; J < NJ; ++J) {
I4 IBuff = (MyList->Offsets[ILayer] + IExch) * NJ + J;
MyNeighbor->SendBuffer[IBuff] =
reinterpret_cast<Real &>(Array(MyList->Ind[ILayer][IExch], J));
reinterpret_cast<R8 &>(Array(MyList->Ind[ILayer][IExch], J));
}
}
}
Expand Down Expand Up @@ -860,7 +860,7 @@ int Halo::packBuffer(const HostArray3DI4 Array) {
I4 IBuff =
(K * MyList->NTot + MyList->Offsets[ILayer] + IExch) * NJ +
J;
MyNeighbor->SendBuffer[IBuff] = reinterpret_cast<Real &>(
MyNeighbor->SendBuffer[IBuff] = reinterpret_cast<R8 &>(
Array(K, MyList->Ind[ILayer][IExch], J));
}
}
Expand All @@ -885,7 +885,7 @@ int Halo::packBuffer(const HostArray3DI8 Array) {
I4 IBuff =
(K * MyList->NTot + MyList->Offsets[ILayer] + IExch) * NJ +
J;
MyNeighbor->SendBuffer[IBuff] = reinterpret_cast<Real &>(
MyNeighbor->SendBuffer[IBuff] = reinterpret_cast<R8 &>(
Array(K, MyList->Ind[ILayer][IExch], J));
}
}
Expand Down Expand Up @@ -963,7 +963,7 @@ int Halo::packBuffer(const HostArray4DI4 Array) {
MyList->Offsets[ILayer] + IExch) *
NJ +
J;
MyNeighbor->SendBuffer[IBuff] = reinterpret_cast<Real &>(
MyNeighbor->SendBuffer[IBuff] = reinterpret_cast<R8 &>(
Array(L, K, MyList->Ind[ILayer][IExch], J));
}
}
Expand Down Expand Up @@ -992,7 +992,7 @@ int Halo::packBuffer(const HostArray4DI8 Array) {
MyList->Offsets[ILayer] + IExch) *
NJ +
J;
MyNeighbor->SendBuffer[IBuff] = reinterpret_cast<Real &>(
MyNeighbor->SendBuffer[IBuff] = reinterpret_cast<R8 &>(
Array(L, K, MyList->Ind[ILayer][IExch], J));
}
}
Expand Down Expand Up @@ -1081,7 +1081,7 @@ int Halo::packBuffer(const HostArray5DI4 Array) {
MyList->Offsets[ILayer] + IExch) *
NJ +
J;
MyNeighbor->SendBuffer[IBuff] = reinterpret_cast<Real &>(
MyNeighbor->SendBuffer[IBuff] = reinterpret_cast<R8 &>(
Array(M, L, K, MyList->Ind[ILayer][IExch], J));
}
}
Expand Down Expand Up @@ -1113,7 +1113,7 @@ int Halo::packBuffer(const HostArray5DI8 Array) {
MyList->Offsets[ILayer] + IExch) *
NJ +
J;
MyNeighbor->SendBuffer[IBuff] = reinterpret_cast<Real &>(
MyNeighbor->SendBuffer[IBuff] = reinterpret_cast<R8 &>(
Array(M, L, K, MyList->Ind[ILayer][IExch], J));
}
}
Expand Down
4 changes: 2 additions & 2 deletions components/omega/src/base/Halo.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ namespace OMEGA {

// Set the default MPI real data type as single or double precision based on
// the default real data type used by OMEGA.
#ifdef SINGLE_PRECISION
#ifdef OMEGA_SINGLE_PRECISION
static const MPI_Datatype MPI_RealKind = MPI_FLOAT;
#else
static const MPI_Datatype MPI_RealKind = MPI_DOUBLE;
Expand Down Expand Up @@ -132,7 +132,7 @@ class Halo {
/// index space. 0 = OnCell, 1 = OnEdge, 2 = OnVertex
ExchList SendLists[3], RecvLists[3];
/// Buffers for MPI communication
std::vector<Real> SendBuffer, RecvBuffer;
std::vector<R8> SendBuffer, RecvBuffer;
/// MPI request handles for non-blocking MPI communication
MPI_Request RReq, SReq;

Expand Down
Loading

0 comments on commit 801ceaa

Please sign in to comment.