From 4eebd492e82fdedf6cb219c613955875de3647c9 Mon Sep 17 00:00:00 2001 From: Jack Poulson Date: Wed, 23 Nov 2016 13:50:49 -0800 Subject: [PATCH] Simplifying custom MPI datatypes and ops --- examples/number_theory/SVPChallenge.cpp | 45 +- include/El/core/imports/mpi.hpp | 38 +- src/core/environment.cpp | 28 +- src/core/mpi_register.cpp | 718 ++++++++++++------------ src/core/random.cpp | 12 +- 5 files changed, 432 insertions(+), 409 deletions(-) diff --git a/examples/number_theory/SVPChallenge.cpp b/examples/number_theory/SVPChallenge.cpp index 368157bbe0..ab594020b7 100644 --- a/examples/number_theory/SVPChallenge.cpp +++ b/examples/number_theory/SVPChallenge.cpp @@ -2,8 +2,8 @@ Copyright (c) 2009-2016, Jack Poulson All rights reserved. - This file is part of Elemental and is under the BSD 2-Clause License, - which can be found in the LICENSE file in the root directory, or at + This file is part of Elemental and is under the BSD 2-Clause License, + which can be found in the LICENSE file in the root directory, or at http://opensource.org/licenses/BSD-2-Clause */ #include @@ -28,9 +28,9 @@ int main( int argc, char* argv[] ) Input("--inputBasisFile","input basis file", string("../data/number_theory/SVPChallenge40.txt")); const bool trans = Input("--transpose","transpose input?",true); - const string outputBasisFile = + const string outputBasisFile = Input("--outputBasisFile","output basis file",string("BKZ")); - const string shortestVecFile = + const string shortestVecFile = Input ("--shortestVecFile","shortest vector file",string("shortest")); const Real delta = Input("--delta","delta for LLL",Real(0.9999)); @@ -73,13 +73,13 @@ int main( int argc, char* argv[] ) const bool timeLLL = Input("--timeLLL","time LLL?",false); const bool timeBKZ = Input("--timeBKZ","time BKZ?",true); const bool progressLLL = - Input("--progressLLL","print LLL progress?",false); + Input("--progressLLL","print LLL progress?",false); const bool progressBKZ = - Input("--progressBKZ","print BKZ progress?",true); + Input("--progressBKZ","print BKZ progress?",true); const bool print = Input("--print","output all matrices?",true); const bool logFailedEnums = Input("--logFailedEnums","log failed enumerations in BKZ?",false); - const bool logStreakSizes = + const bool logStreakSizes = Input("--logStreakSizes","log enum streak sizes in BKZ?",false); const bool logNontrivialCoords = Input("--logNontrivialCoords","log nontrivial enum coords?",false); @@ -107,18 +107,18 @@ int main( int argc, char* argv[] ) mpfr::SetPrecision( prec ); #endif - Matrix B; + Matrix B; if( trans ) { Matrix BTrans; Read( BTrans, inputBasisFile ); - Transpose( BTrans, B ); + Transpose( BTrans, B ); } else Read( B, inputBasisFile ); const Int m = B.Height(); const Int n = B.Width(); - const Real BOrigOne = OneNorm( B ); + const Real BOrigOne = OneNorm( B ); Output("|| B_orig ||_1 = ",BOrigOne); if( print ) Print( B, "BOrig" ); @@ -155,7 +155,7 @@ int main( int argc, char* argv[] ) return 45; */ }; - auto enumTypeLambda = + auto enumTypeLambda = [&]( Int j ) { if( j <= 3 ) @@ -178,7 +178,7 @@ int main( int argc, char* argv[] ) ctrl.startCol = startColBKZ; ctrl.enumCtrl.enumType = FULL_ENUM; ctrl.enumCtrl.time = timeEnum; - ctrl.enumCtrl.innerProgress = innerEnumProgress; + ctrl.enumCtrl.innerProgress = innerEnumProgress; ctrl.enumCtrl.phaseLength = phaseLength; ctrl.enumCtrl.enqueueProb = enqueueProb; ctrl.enumCtrl.progressLevel = progressLevel; @@ -210,6 +210,7 @@ int main( int argc, char* argv[] ) ctrl.enumCtrl.customMaxOneNorms = true; const Int startIndex = Max(n/2-1,0); const Int numPhases = ((n-startIndex)+phaseLength-1) / phaseLength; + Output("numPhases=",numPhases); ctrl.enumCtrl.minInfNorms.resize( numPhases, 0 ); ctrl.enumCtrl.maxInfNorms.resize( numPhases, 1 ); ctrl.enumCtrl.minOneNorms.resize( numPhases, 0 ); @@ -248,7 +249,7 @@ int main( int argc, char* argv[] ) auto info = BKZ( B, R, ctrl ); const double runTime = mpi::Time() - startTime; Output - (" BKZ(",blocksize,",",delta,",",eta,") took ",runTime," seconds"); + (" BKZ(",blocksize,",",delta,",",eta,") took ",runTime," seconds"); Output(" achieved delta: ",info.delta); Output(" achieved eta: ",info.eta); Output(" num swaps: ",info.numSwaps); @@ -261,7 +262,7 @@ int main( int argc, char* argv[] ) Output(" targetRatio*GH(L): ",challenge); if( print ) { - Print( B, "B" ); + Print( B, "B" ); Print( R, "R" ); } Write( B, outputBasisFile, ASCII, "BKZ" ); @@ -289,7 +290,7 @@ int main( int argc, char* argv[] ) if( !succeeded || fullEnum ) { - const Int start = 0; + const Int start = 0; const Int numCols = n; const Range subInd( start, start+numCols ); auto BSub = B( ALL, subInd ); @@ -304,11 +305,17 @@ int main( int argc, char* argv[] ) timer.Start(); Real result; if( fullEnum ) - result = - ShortestVectorEnumeration( BSub, RSub, target, v, enumCtrl ); + { + result = + ShortestVectorEnumeration( BSub, RSub, target, v, enumCtrl ); + Output("shortest vector result = ",result); + } else - result = - ShortVectorEnumeration( BSub, RSub, target, v, enumCtrl ); + { + result = + ShortVectorEnumeration( BSub, RSub, target, v, enumCtrl ); + Output("short vector result = ",result); + } Output("Enumeration: ",timer.Stop()," seconds"); if( result < target ) { diff --git a/include/El/core/imports/mpi.hpp b/include/El/core/imports/mpi.hpp index 02d22a7334..d4bf099d24 100644 --- a/include/El/core/imports/mpi.hpp +++ b/include/El/core/imports/mpi.hpp @@ -133,12 +133,40 @@ const Op BINARY_XOR = MPI_BXOR; template struct Types { + static bool createdTypeBeforeResize; + static El::mpi::Datatype typeBeforeResize; + + static bool createdType; static El::mpi::Datatype type; - // CAUTION: These are not defined for all types - static El::mpi::Op sumOp, prodOp, - minOp, maxOp, - userOp, userCommOp; + + static bool haveSumOp; + static bool createdSumOp; + static El::mpi::Op sumOp; + + static bool haveProdOp; + static bool createdProdOp; + static El::mpi::Op prodOp; + + static bool haveMinOp; + static bool createdMinOp; + static El::mpi::Op minOp; + + static bool haveMaxOp; + static bool createdMaxOp; + static El::mpi::Op maxOp; + + static bool haveUserOp; + static bool createdUserOp; + static El::mpi::Op userOp; + + static bool haveUserCommOp; + static bool createdUserCommOp; + static El::mpi::Op userCommOp; + static function userFunc, userCommFunc; + + // Internally called once per type between MPI_Init and MPI_Finalize + static void Destroy(); }; template @@ -1075,8 +1103,6 @@ void VerifySendsAndRecvs void CreateCustom() EL_NO_RELEASE_EXCEPT; void DestroyCustom() EL_NO_RELEASE_EXCEPT; -template Datatype& TypeMap() EL_NO_EXCEPT; - #ifdef EL_HAVE_MPC void CreateBigIntFamily(); void DestroyBigIntFamily(); diff --git a/src/core/environment.cpp b/src/core/environment.cpp index 243950e4c6..a78db16be7 100644 --- a/src/core/environment.cpp +++ b/src/core/environment.cpp @@ -3,8 +3,8 @@ 2013, Jeff Hammond All rights reserved. - This file is part of Elemental and is under the BSD 2-Clause License, - which can be found in the LICENSE file in the root directory, or at + This file is part of Elemental and is under the BSD 2-Clause License, + which can be found in the LICENSE file in the root directory, or at http://opensource.org/licenses/BSD-2-Clause */ #include @@ -35,7 +35,7 @@ void PrintVersion( ostream& os ) void PrintConfig( ostream& os ) { - os << + os << "Elemental configuration:\n" << " Math libraries: " << EL_MATH_LIBS << "\n" #ifdef EL_HAVE_FLA_BSVD @@ -148,7 +148,7 @@ void Initialize( int& argc, char**& argv ) ("Cannot initialize elemental after finalizing MPI"); } #ifdef EL_HYBRID - const Int provided = + const Int provided = mpi::InitializeThread ( argc, argv, mpi::THREAD_MULTIPLE ); const int commRank = mpi::Rank( mpi::COMM_WORLD ); @@ -191,8 +191,8 @@ void Initialize( int& argc, char**& argv ) InitializeRandom(); - // Create the types and ops - // NOTE: mpfr::SetPrecision created the BigFloat types + // Create the types and ops. + // mpfr::SetPrecision within InitializeRandom created the BigFloat types mpi::CreateCustom(); } @@ -200,7 +200,7 @@ void Finalize() { DEBUG_CSE if( ::numElemInits <= 0 ) - { + { cerr << "Finalized Elemental more times than initialized" << endl; return; } @@ -214,7 +214,7 @@ void Finalize() ::args = 0; Grid::FinalizeDefault(); - + // Destroy the types and ops mpi::DestroyCustom(); @@ -242,10 +242,10 @@ void Finalize() } Args& GetArgs() -{ +{ if( args == 0 ) throw std::runtime_error("No available instance of Args"); - return *::args; + return *::args; } void Args::HandleVersion( ostream& os ) const @@ -292,15 +292,15 @@ void ReportException( const exception& e, ostream& os ) { if( string(e.what()) != "" ) { - os << "Process " << mpi::Rank() + os << "Process " << mpi::Rank() << " caught an unrecoverable exception with message:\n" << e.what() << endl; } DEBUG_ONLY(DumpCallStack(os)) mpi::Abort( mpi::COMM_WORLD, 1 ); } - catch( exception& castExcept ) - { + catch( exception& castExcept ) + { if( string(e.what()) != "" ) { os << "Process " << mpi::Rank() << " caught error message:\n" @@ -352,7 +352,7 @@ void Union { both.resize( first.size()+second.size() ); auto it = std::set_union - ( first.cbegin(), first.cend(), + ( first.cbegin(), first.cend(), second.cbegin(), second.cend(), both.begin() ); both.resize( Int(it-both.begin()) ); diff --git a/src/core/mpi_register.cpp b/src/core/mpi_register.cpp index c1f880dfa8..c60a8e5943 100644 --- a/src/core/mpi_register.cpp +++ b/src/core/mpi_register.cpp @@ -2,8 +2,8 @@ Copyright (c) 2009-2016, Jack Poulson All rights reserved. - This file is part of Elemental and is under the BSD 2-Clause License, - which can be found in the LICENSE file in the root directory, or at + This file is part of Elemental and is under the BSD 2-Clause License, + which can be found in the LICENSE file in the root directory, or at http://opensource.org/licenses/BSD-2-Clause */ #include @@ -16,20 +16,9 @@ namespace mpi { // Datatypes // ========= -// Provide default datatypes (though they should not end up being used) - +// Provide default datatype (it should not end up being used) template -Datatype Types::type = MPI_UNSIGNED_CHAR; - -template Op Types::sumOp = MPI_SUM; -template Op Types::prodOp = MPI_PROD; -template Op Types::maxOp = MPI_MAX; -template Op Types::minOp = MPI_MIN; -template Op Types::userOp = MPI_SUM; -template Op Types::userCommOp = MPI_SUM; - -template function Types::userFunc; -template function Types::userCommFunc; +Datatype Types::type = MPI_DATATYPE_NULL; template<> Datatype Types::type = MPI_UNSIGNED_CHAR; template<> Datatype Types::type = MPI_SHORT; @@ -44,13 +33,13 @@ template<> Datatype Types::type = MPI_UNSIGNED_LONG_LONG; template<> Datatype Types::type = MPI_FLOAT; template<> Datatype Types::type = MPI_DOUBLE; /* I'm not sure of whether it is better to manually implement these - or not. MPI_COMPLEX and MPI_DOUBLE_COMPLEX are dangerous since it - appears that recent versions of MPICH leave them as NULL when - compiling with Clang. + or not. MPI_COMPLEX and MPI_DOUBLE_COMPLEX are dangerous since it + appears that recent versions of MPICH leave them as NULL when + compiling with Clang. - It also appears that certain versions of OpenMPI do not support + It also appears that certain versions of OpenMPI do not support MPI_C_FLOAT_COMPLEX and MPI_C_DOUBLE_COMPLEX, and so we will, for now, - use these by default and fall back to MPI_COMPLEX and + use these by default and fall back to MPI_COMPLEX and MPI_DOUBLE_COMPLEX otherwise. */ #ifdef EL_HAVE_MPI_C_COMPLEX template<> Datatype Types>::type = MPI_C_FLOAT_COMPLEX; @@ -60,6 +49,58 @@ template<> Datatype Types>::type = MPI_COMPLEX; template<> Datatype Types>::type = MPI_DOUBLE_COMPLEX; #endif +template +bool Types::createdTypeBeforeResize = false; +template +Datatype Types::typeBeforeResize = MPI_DATATYPE_NULL; +template +bool Types::createdType = false; + +template +bool Types::haveSumOp = true; +template +bool Types::createdSumOp = false; +template +Op Types::sumOp = MPI_SUM; + +template +bool Types::haveProdOp = true; +template +bool Types::createdProdOp = false; +template +Op Types::prodOp = MPI_PROD; + +template +bool Types::haveMaxOp = true; +template +bool Types::createdMaxOp = false; +template +Op Types::maxOp = MPI_MAX; + +template +bool Types::haveMinOp = true; +template +bool Types::createdMinOp = false; +template +Op Types::minOp = MPI_MIN; + +template +bool Types::haveUserOp = true; +template +bool Types::createdUserOp = false; +template +Op Types::userOp = MPI_SUM; + +template +bool Types::haveUserCommOp = true; +template +bool Types::createdUserCommOp = false; +template +Op Types::userCommOp = MPI_SUM; + +template function Types::userFunc; +template function Types::userCommFunc; + template struct Types; template struct Types; template struct Types; @@ -87,55 +128,155 @@ template struct Types; // Avoid conflict with Int #define EL_ENABLE_BIGFLOAT #include -// TODO: ValueInt user functions and ops -// TODO: ValueIntPair user functions and ops +// TODO(poulson): ValueInt user functions and ops +// TODO(poulson): ValueIntPair user functions and ops + +template +void Types::Destroy() +{ + if( createdUserCommOp ) + { + Free( userCommOp ); + haveUserCommOp = false; + createdUserCommOp = false; + } + if( createdUserOp ) + { + Free( userOp ); + haveUserOp = false; + createdUserOp = false; + } + if( createdMaxOp ) + { + Free( maxOp ); + haveMaxOp = false; + createdMaxOp = false; + } + if( createdMinOp ) + { + Free( minOp ); + haveMinOp = false; + createdMinOp = false; + } + if( createdProdOp ) + { + Free( prodOp ); + haveProdOp = false; + createdProdOp = false; + } + if( createdSumOp ) + { + Free( sumOp ); + haveSumOp = false; + createdSumOp = false; + } + if( createdType ) + { + DEBUG_ONLY( + if( type == MPI_DATATYPE_NULL ) + LogicError + ("Types<",TypeName(),">::type == MPI_DATATYPE_NULL in Free"); + ) + Free( type ); + createdType = false; + } + if( createdTypeBeforeResize ) + { + DEBUG_ONLY( + if( typeBeforeResize == MPI_DATATYPE_NULL ) + LogicError + ("Types<",TypeName(), + ">::typeBeforeResize == MPI_DATATYPE_NULL in Free"); + ) + Free( typeBeforeResize ); + createdTypeBeforeResize = false; + } +} namespace { // The first stage; to be finalized via 'CreateResized'. -// TODO: Decide whether the intermediate type (i.e., 'newType') needs to be -// committed and/or freed. +template void CreateStruct ( int numItems, int* blockLengths, MPI_Aint* displs, - Datatype* typeList, - Datatype& newType ) + Datatype* typeList ) { int err = MPI_Type_create_struct - ( numItems, blockLengths, displs, typeList, &newType ); + ( numItems, blockLengths, displs, typeList, &Types::typeBeforeResize ); if( err != MPI_SUCCESS ) RuntimeError("MPI_Type_create_struct returned with err=",err); + Types::createdTypeBeforeResize = true; } -void CreateResized -( Datatype& type, - MPI_Aint lowerBound, - MPI_Aint extent, - Datatype& newType ) +template +void Commit() { - int err = MPI_Type_create_resized( type, 0, extent, &newType ); + // Ensure that we can communicate using this datatype + int err = MPI_Type_commit( &Types::type ); if( err != MPI_SUCCESS ) - RuntimeError("MPI_Type_create_resized returned with err=",err); + RuntimeError("MPI_Type_commit returned with err=",err); +} - err = MPI_Type_commit( &newType ); +template +void CreateResized( MPI_Aint lowerBound, MPI_Aint extent ) +{ + int err = + MPI_Type_create_resized + ( Types::typeBeforeResize, 0, extent, &Types::type ); if( err != MPI_SUCCESS ) - RuntimeError("MPI_Type_commit returned with err=",err); + RuntimeError("MPI_Type_create_resized returned with err=",err); + Types::createdType = true; + Commit(); } -void CreateContiguous -( int numItems, - Datatype type, - Datatype& newType ) +template +void CreateContiguous( int numItems, Datatype type ) { - int err = MPI_Type_contiguous( numItems, type, &newType ); + int err = MPI_Type_contiguous( numItems, type, &Types::type ); if( err != MPI_SUCCESS ) RuntimeError("MPI_Type_contiguous returned with err=",err); + Types::createdType = true; + Commit(); +} - err = MPI_Type_commit( &newType ); - if( err != MPI_SUCCESS ) - RuntimeError("MPI_Type_commit returned with err=",err); +template +void FreeResized() +{ + if( Types::createdType ) + { + if( Types::type == MPI_DATATYPE_NULL ) + LogicError + ("Types<",TypeName(),">::type == MPI_DATATYPE_NULL in Free"); + Free( Types::type ); + Types::createdType = false; + } + if( Types::createdTypeBeforeResize ) + { + if( Types::typeBeforeResize == MPI_DATATYPE_NULL ) + LogicError + ("Types<",TypeName(), + ">::typeBeforeResize == MPI_DATATYPE_NULL in Free"); + Free( Types::typeBeforeResize ); + Types::createdTypeBeforeResize = false; + } +} + +template +void FreeResizedFamily() +{ + FreeResized>(); + FreeResized>(); + FreeResized(); +} + +template +void FreeResizedScalarFamily() +{ + FreeResizedFamily>(); + FreeResizedFamily(); } } // anonymous namespace @@ -151,7 +292,7 @@ void CreateBigIntType() Datatype typeList[2]; typeList[0] = TypeMap(); typeList[1] = TypeMap(); - + int blockLengths[2]; blockLengths[0] = 1; blockLengths[1] = numLimbs; @@ -159,10 +300,9 @@ void CreateBigIntType() MPI_Aint displs[2]; displs[0] = 0; displs[1] = sizeof(int); - - MPI_Datatype tempType; - CreateStruct( 2, blockLengths, displs, typeList, tempType ); - CreateResized( tempType, 0, packedSize, TypeMap() ); + + CreateStruct( 2, blockLengths, displs, typeList ); + CreateResized( 0, packedSize ); } void CreateBigFloatType() @@ -176,10 +316,10 @@ void CreateBigFloatType() typeList[1] = TypeMap(); typeList[2] = TypeMap(); typeList[3] = TypeMap(); - + int blockLengths[4]; blockLengths[0] = 1; - blockLengths[1] = 1; + blockLengths[1] = 1; blockLengths[2] = 1; blockLengths[3] = numLimbs; @@ -188,21 +328,12 @@ void CreateBigFloatType() displs[1] = sizeof(mpfr_prec_t); displs[2] = sizeof(mpfr_prec_t) + sizeof(mpfr_sign_t); displs[3] = sizeof(mpfr_prec_t) + sizeof(mpfr_sign_t) + sizeof(mpfr_exp_t); - - MPI_Datatype tempType; - CreateStruct( 4, blockLengths, displs, typeList, tempType ); - CreateResized( tempType, 0, packedSize, TypeMap() ); + + CreateStruct( 4, blockLengths, displs, typeList ); + CreateResized( 0, packedSize ); } #endif // ifdef EL_HAVE_MPC -// TODO: Expose hooks for these routines so that the user could run -// -// AllReduce -// ( value, -// []( const T& alpha, const T& beta ) { return Min(alpha,beta); } -// comm ) -// - template>> static void UserReduce @@ -233,7 +364,7 @@ EL_NO_EXCEPT b.Deserialize(outData); b = func(a,b); - outData = b.Serialize(outData); + outData = b.Serialize(outData); } } @@ -267,7 +398,7 @@ EL_NO_EXCEPT b.Deserialize(outData); b = func(a,b); - outData = b.Serialize(outData); + outData = b.Serialize(outData); } } @@ -365,7 +496,7 @@ EL_NO_EXCEPT b.Deserialize(outData); b += a; - outData = b.Serialize(outData); + outData = b.Serialize(outData); } } @@ -395,7 +526,7 @@ EL_NO_EXCEPT b.Deserialize(outData); b *= a; - outData = b.Serialize(outData); + outData = b.Serialize(outData); } } @@ -403,7 +534,7 @@ template>> static void MaxLocFunc( void* inVoid, void* outVoid, int* lengthPtr, Datatype* datatype ) EL_NO_EXCEPT -{ +{ auto inData = static_cast*>(inVoid); auto outData = static_cast< ValueInt*>(outVoid); const int length = *lengthPtr; @@ -412,7 +543,7 @@ EL_NO_EXCEPT const T inVal = inData[j].value; const T outVal = outData[j].value; const Int inInd = inData[j].index; - const Int outInd = outData[j].index; + const Int outInd = outData[j].index; if( inVal > outVal || (inVal == outVal && inInd < outInd) ) outData[j] = inData[j]; } @@ -442,7 +573,7 @@ template>> static void MinLocFunc( void* inVoid, void* outVoid, int* lengthPtr, Datatype* datatype ) EL_NO_EXCEPT -{ +{ auto inData = static_cast*>(inVoid); auto outData = static_cast< ValueInt*>(outVoid); const int length = *lengthPtr; @@ -451,7 +582,7 @@ EL_NO_EXCEPT const T inVal = inData[j].value; const T outVal = outData[j].value; const Int inInd = inData[j].index; - const Int outInd = outData[j].index; + const Int outInd = outData[j].index; if( inVal < outVal || (inVal == outVal && inInd < outInd) ) outData[j] = inData[j]; } @@ -567,10 +698,10 @@ static void CreateValueIntType() EL_NO_EXCEPT Datatype typeList[2]; typeList[0] = TypeMap(); typeList[1] = TypeMap(); - + int blockLengths[2]; blockLengths[0] = 1; - blockLengths[1] = 1; + blockLengths[1] = 1; ValueInt v; MPI_Aint startAddr, valueAddr, indexAddr; @@ -582,11 +713,10 @@ static void CreateValueIntType() EL_NO_EXCEPT displs[0] = valueAddr - startAddr; displs[1] = indexAddr - startAddr; - Datatype tempType; - CreateStruct( 2, blockLengths, displs, typeList, tempType ); - MPI_Aint extent = sizeof(v); - CreateResized( tempType, 0, extent, TypeMap>() ); + + CreateStruct>( 2, blockLengths, displs, typeList ); + CreateResized>( 0, extent ); } template>,typename=void> @@ -597,10 +727,10 @@ void CreateValueIntType() EL_NO_EXCEPT Datatype typeList[2]; typeList[0] = TypeMap(); typeList[1] = TypeMap(); - + int blockLengths[2]; blockLengths[0] = 1; - blockLengths[1] = 1; + blockLengths[1] = 1; T alpha; const size_t packedSize = alpha.SerializedSize(); @@ -609,11 +739,10 @@ void CreateValueIntType() EL_NO_EXCEPT displs[0] = 0; displs[1] = packedSize; - Datatype tempType; - CreateStruct( 2, blockLengths, displs, typeList, tempType ); - MPI_Aint extent = packedSize + sizeof(Int); - CreateResized( tempType, 0, extent, TypeMap>() ); + + CreateStruct>( 2, blockLengths, displs, typeList ); + CreateResized>( 0, extent ); } template>> @@ -625,11 +754,11 @@ static void CreateEntryType() EL_NO_EXCEPT typeList[0] = TypeMap(); typeList[1] = TypeMap(); typeList[2] = TypeMap(); - + int blockLengths[3]; blockLengths[0] = 1; - blockLengths[1] = 1; - blockLengths[2] = 1; + blockLengths[1] = 1; + blockLengths[2] = 1; Entry v; MPI_Aint startAddr, iAddr, jAddr, valueAddr; @@ -643,11 +772,10 @@ static void CreateEntryType() EL_NO_EXCEPT displs[1] = jAddr - startAddr; displs[2] = valueAddr - startAddr; - Datatype tempType; - CreateStruct( 3, blockLengths, displs, typeList, tempType ); - MPI_Aint extent = sizeof(v); - CreateResized( tempType, 0, extent, TypeMap>() ); + + CreateStruct>( 3, blockLengths, displs, typeList ); + CreateResized>( 0, extent ); } template>,typename=void> @@ -659,25 +787,23 @@ void CreateEntryType() EL_NO_EXCEPT typeList[0] = TypeMap(); typeList[1] = TypeMap(); typeList[2] = TypeMap(); - + int blockLengths[3]; blockLengths[0] = 1; - blockLengths[1] = 1; - blockLengths[2] = 1; + blockLengths[1] = 1; + blockLengths[2] = 1; MPI_Aint displs[3]; displs[0] = 0; displs[1] = sizeof(Int); displs[2] = 2*sizeof(Int); - Datatype tempType; - CreateStruct( 3, blockLengths, displs, typeList, tempType ); - T alpha; const auto packedSize = alpha.SerializedSize(); - MPI_Aint extent = 2*sizeof(Int) + packedSize; - CreateResized( tempType, 0, extent, TypeMap>() ); + + CreateStruct>( 3, blockLengths, displs, typeList ); + CreateResized>( 0, extent ); } #ifdef EL_HAVE_MPC @@ -691,8 +817,7 @@ void CreateBigIntFamily() void CreateBigFloatFamily() { CreateBigFloatType(); - CreateContiguous - ( 2, Types::type, Types>::type ); + CreateContiguous>( 2, Types::type ); CreateValueIntType(); CreateValueIntType>(); @@ -703,21 +828,12 @@ void CreateBigFloatFamily() void DestroyBigIntFamily() { - Free( Types>::type ); - Free( Types>::type ); - Free( Types::type ); + FreeResizedFamily(); } void DestroyBigFloatFamily() { - - Free( Types>>::type ); - Free( Types>>::type ); - Free( Types>::type ); - - Free( Types>::type ); - Free( Types>::type ); - Free( Types::type ); + FreeResizedScalarFamily(); } #endif @@ -726,372 +842,246 @@ void CreateUserOps() { Create( (UserFunction*)UserReduce, false, UserOp() ); Create( (UserFunction*)UserReduceComm, true, UserCommOp() ); + Types::createdUserOp = true; + Types::createdUserCommOp = true; } template void CreateSumOp() { Create( (UserFunction*)SumFunc, true, SumOp() ); + Types::createdSumOp = true; } template void CreateProdOp() { Create( (UserFunction*)ProdFunc, true, ProdOp() ); + Types::createdProdOp = true; } template void CreateMaxOp() { Create( (UserFunction*)MaxFunc, true, MaxOp() ); + Types::createdMaxOp = true; } template void CreateMinOp() { Create( (UserFunction*)MinFunc, true, MinOp() ); + Types::createdMinOp = true; } template void CreateMaxLocOp() { Create( (UserFunction*)MaxLocFunc, true, MaxLocOp() ); + Types>::createdMaxOp = true; } template void CreateMinLocOp() { Create( (UserFunction*)MinLocFunc, true, MinLocOp() ); + Types>::createdMinOp = true; } template void CreateMaxLocPairOp() { Create( (UserFunction*)MaxLocPairFunc, true, MaxLocPairOp() ); + Types>::createdMaxOp = true; } template void CreateMinLocPairOp() { Create( (UserFunction*)MinLocPairFunc, true, MinLocPairOp() ); + Types>::createdMinOp = true; } void CreateCustom() EL_NO_RELEASE_EXCEPT { - // Create the necessary types - // ========================== -#ifdef EL_HAVE_QD - CreateContiguous( 2, MPI_DOUBLE, TypeMap() ); - CreateContiguous( 4, MPI_DOUBLE, TypeMap() ); - CreateContiguous - ( 2, TypeMap(), TypeMap>() ); - CreateContiguous - ( 2, TypeMap(), TypeMap>() ); -#endif -#ifdef EL_HAVE_QUAD - CreateContiguous( 2, MPI_DOUBLE, TypeMap() ); - CreateContiguous( 4, MPI_DOUBLE, TypeMap>() ); -#endif - // NOTE: The BigFloat types are created by mpfr::SetPrecision previously - // within El::Initialize - - // A value and an integer - // ---------------------- + // Int + // === CreateValueIntType(); + CreateEntryType(); + CreateUserOps(); + CreateMaxLocOp(); + CreateMinLocOp(); + CreateMaxLocPairOp(); + CreateMinLocPairOp(); + + // float + // ===== #ifdef EL_USE_64BIT_INTS CreateValueIntType(); - CreateValueIntType(); #else TypeMap>() = MPI_FLOAT_INT; - TypeMap>() = MPI_DOUBLE_INT; #endif CreateValueIntType>(); - CreateValueIntType>(); -#ifdef EL_HAVE_QD - CreateValueIntType(); - CreateValueIntType(); - CreateValueIntType>(); - CreateValueIntType>(); -#endif -#ifdef EL_HAVE_QUAD - CreateValueIntType(); - CreateValueIntType>(); -#endif - - // A triplet of a value and a pair of integers - // ------------------------------------------- - CreateEntryType(); CreateEntryType(); - CreateEntryType(); CreateEntryType>(); - CreateEntryType>(); -#ifdef EL_HAVE_QD - CreateEntryType(); - CreateEntryType(); - CreateEntryType>(); - CreateEntryType>(); -#endif -#ifdef EL_HAVE_QUAD - CreateEntryType(); - CreateEntryType>(); + CreateUserOps(); + CreateUserOps>(); +#ifdef EL_USE_64BIT_INTS + CreateMaxLocOp(); + CreateMinLocOp(); +#else + MaxLocOp() = MAXLOC; + MinLocOp() = MINLOC; #endif + CreateMaxLocPairOp(); + CreateMinLocPairOp(); - // Create the necessary MPI operations - // =================================== - // Functions for user-defined ops - // ------------------------------ - CreateUserOps(); - CreateUserOps(); + // double + // ====== +#ifdef EL_USE_64BIT_INTS + CreateValueIntType(); +#else + TypeMap>() = MPI_DOUBLE_INT; +#endif + CreateValueIntType>(); + CreateEntryType(); + CreateEntryType>(); CreateUserOps(); - CreateUserOps>(); CreateUserOps>(); +#ifdef EL_USE_64BIT_INTS + CreateMaxLocOp(); + CreateMinLocOp(); +#else + MaxLocOp() = MAXLOC; + MinLocOp() = MINLOC; +#endif + CreateMaxLocPairOp(); + CreateMinLocPairOp(); + #ifdef EL_HAVE_QD + // DoubleDouble + // ============ + CreateContiguous( 2, MPI_DOUBLE ); + CreateContiguous>( 2, TypeMap() ); + CreateValueIntType(); + CreateValueIntType>(); + CreateEntryType(); + CreateEntryType>(); CreateUserOps(); - CreateUserOps(); CreateUserOps>(); - CreateUserOps>(); -#endif -#ifdef EL_HAVE_QUAD - CreateUserOps(); - CreateUserOps>(); -#endif -#ifdef EL_HAVE_MPC - CreateUserOps(); - CreateUserOps(); - CreateUserOps>(); -#endif - - // Functions for scalar types - // -------------------------- -#ifdef EL_HAVE_QD CreateMaxOp(); CreateMinOp(); CreateSumOp(); CreateProdOp(); + CreateSumOp>(); + CreateProdOp>(); + CreateMaxLocOp(); + CreateMinLocOp(); + CreateMaxLocPairOp(); + CreateMinLocPairOp(); + // QuadDouble + // ========== + CreateContiguous( 4, MPI_DOUBLE ); + CreateContiguous>( 2, TypeMap() ); + CreateValueIntType(); + CreateValueIntType>(); + CreateEntryType(); + CreateEntryType>(); + CreateUserOps(); + CreateUserOps>(); CreateMaxOp(); CreateMinOp(); CreateSumOp(); CreateProdOp(); - - CreateSumOp>(); CreateSumOp>(); - CreateProdOp>(); CreateProdOp>(); + CreateMaxLocOp(); + CreateMinLocOp(); + CreateMaxLocPairOp(); + CreateMinLocPairOp(); #endif + #ifdef EL_HAVE_QUAD + // Quad + // ==== + CreateContiguous( 2, MPI_DOUBLE ); + CreateContiguous>( 2, TypeMap() ); + CreateValueIntType(); + CreateValueIntType>(); + CreateEntryType(); + CreateEntryType>(); + CreateUserOps(); + CreateUserOps>(); CreateMaxOp(); CreateMinOp(); CreateSumOp(); CreateProdOp(); - CreateSumOp>(); CreateProdOp>(); + CreateMaxLocOp(); + CreateMinLocOp(); + CreateMaxLocPairOp(); + CreateMinLocPairOp(); #endif -#ifdef EL_HAVE_MPC - CreateMaxOp(); - CreateMinOp(); - CreateSumOp(); - CreateProdOp(); +#ifdef EL_HAVE_MPC + // BigFloat + // ======== + // NOTE: The BigFloat types are created by mpfr::SetPrecision previously + // within El::Initialize + CreateUserOps(); + CreateUserOps>(); CreateMaxOp(); CreateMinOp(); CreateSumOp(); CreateProdOp(); - CreateSumOp>(); CreateProdOp>(); -#endif - // Functions for the value and integer - // ----------------------------------- - CreateMaxLocOp(); - CreateMinLocOp(); -#ifdef EL_USE_64BIT_INTS - CreateMaxLocOp(); - CreateMinLocOp(); - - CreateMaxLocOp(); - CreateMinLocOp(); -#else - MaxLocOp() = MAXLOC; - MinLocOp() = MINLOC; - - MaxLocOp() = MAXLOC; - MinLocOp() = MINLOC; -#endif -#ifdef EL_HAVE_QD - CreateMaxLocOp(); - CreateMinLocOp(); - - CreateMaxLocOp(); - CreateMinLocOp(); -#endif -#ifdef EL_HAVE_QUAD - CreateMaxLocOp(); - CreateMinLocOp(); -#endif -#ifdef EL_HAVE_MPC - CreateMaxLocOp(); - CreateMinLocOp(); - CreateMaxLocOp(); CreateMinLocOp(); -#endif - - // Functions for the triplet of a value and a pair of integers - // ----------------------------------------------------------- - CreateMaxLocPairOp(); - CreateMinLocPairOp(); - - CreateMaxLocPairOp(); - CreateMinLocPairOp(); - - CreateMaxLocPairOp(); - CreateMinLocPairOp(); -#ifdef EL_HAVE_QD - CreateMaxLocPairOp(); - CreateMinLocPairOp(); + CreateMaxLocPairOp(); + CreateMinLocPairOp(); - CreateMaxLocPairOp(); - CreateMinLocPairOp(); -#endif -#ifdef EL_HAVE_QUAD - CreateMaxLocPairOp(); - CreateMinLocPairOp(); -#endif -#ifdef EL_HAVE_MPC + // BigInt + // ====== + CreateUserOps(); + CreateMaxOp(); + CreateMinOp(); + CreateSumOp(); + CreateProdOp(); + CreateMaxLocOp(); + CreateMinLocOp(); CreateMaxLocPairOp(); CreateMinLocPairOp(); - - CreateMaxLocPairOp(); - CreateMinLocPairOp(); #endif } template -void FreeUserOps() +void DestroyFamily() { - Free( Types::userOp ); - Free( Types::userCommOp ); + Types>::Destroy(); + Types>::Destroy(); + Types::Destroy(); } template -void FreeMaxMinOps() +void DestroyScalarFamily() { - Free( Types::maxOp ); - Free( Types::minOp ); -} - -template -void FreeScalarOps() -{ - if( IsReal::value ) - { - FreeMaxMinOps(); - FreeMaxMinOps>(); - FreeMaxMinOps>(); - } - Free( Types::sumOp ); - Free( Types::prodOp ); + DestroyFamily>(); + DestroyFamily(); } void DestroyCustom() EL_NO_RELEASE_EXCEPT { - // Destroy the created operations - // ============================== - - // User-defined operations - // ----------------------- - FreeUserOps(); - FreeUserOps(); - FreeUserOps(); - FreeUserOps>(); - FreeUserOps>(); -#ifdef EL_HAVE_QD - FreeUserOps(); - FreeUserOps(); - FreeUserOps>(); - FreeUserOps>(); -#endif -#ifdef EL_HAVE_QUAD - FreeUserOps(); - FreeUserOps>(); -#endif -#ifdef EL_HAVE_MPC - FreeUserOps(); - FreeUserOps(); - FreeUserOps>(); -#endif - -#ifdef EL_HAVE_QD - FreeScalarOps(); - FreeScalarOps(); - FreeScalarOps>(); - FreeScalarOps>(); -#endif -#ifdef EL_HAVE_QUAD - FreeScalarOps(); - FreeScalarOps>(); -#endif -#ifdef EL_HAVE_MPC - FreeScalarOps(); - FreeScalarOps(); - FreeScalarOps>(); -#endif - - FreeMaxMinOps>(); -#ifdef EL_USE_64BIT_INTS - FreeMaxMinOps>(); - FreeMaxMinOps>(); -#endif - FreeMaxMinOps>(); - FreeMaxMinOps>(); - FreeMaxMinOps>(); - - // Destroy the created types - // ========================= - Free( Types>::type ); - Free( Types>::type ); - Free( Types>::type ); - Free( Types>>::type ); - Free( Types>>::type ); -#ifdef EL_HAVE_QD - Free( Types>::type ); - Free( Types>::type ); - Free( Types>>::type ); - Free( Types>>::type ); -#endif -#ifdef EL_HAVE_QUAD - Free( Types>::type ); - Free( Types>>::type ); -#endif - - Free( Types>::type ); -#ifdef EL_USE_64BIT_INTS - Free( Types>::type ); - Free( Types>::type ); -#endif - Free( Types>>::type ); - Free( Types>>::type ); -#ifdef EL_HAVE_QD - Free( Types>::type ); - Free( Types>::type ); - Free( Types>>::type ); - Free( Types>>::type ); -#endif -#ifdef EL_HAVE_QUAD - Free( Types>::type ); - Free( Types>>::type ); -#endif - + DestroyFamily(); + DestroyScalarFamily(); + DestroyScalarFamily(); #ifdef EL_HAVE_QD - Free( Types>::type ); - Free( Types>::type ); - Free( Types::type ); - Free( Types::type ); + DestroyScalarFamily(); + DestroyScalarFamily(); #endif #ifdef EL_HAVE_QUAD - Free( Types>::type ); - Free( Types::type ); + DestroyScalarFamily(); #endif #ifdef EL_HAVE_MPC - DestroyBigIntFamily(); - DestroyBigFloatFamily(); + DestroyScalarFamily(); + DestroyFamily(); #endif } diff --git a/src/core/random.cpp b/src/core/random.cpp index c02fedb0b5..dc1cbc4309 100644 --- a/src/core/random.cpp +++ b/src/core/random.cpp @@ -2,8 +2,8 @@ Copyright (c) 2009-2016, Jack Poulson All rights reserved. - This file is part of Elemental and is under the BSD 2-Clause License, - which can be found in the LICENSE file in the root directory, or at + This file is part of Elemental and is under the BSD 2-Clause License, + which can be found in the LICENSE file in the root directory, or at http://opensource.org/licenses/BSD-2-Clause */ #include @@ -86,7 +86,7 @@ Quad SampleUniform( const Quad& a, const Quad& b ) template<> BigFloat SampleUniform( const BigFloat& a, const BigFloat& b ) { - BigFloat sample; + BigFloat sample; gmp_randstate_t randState; mpfr::RandomState( randState ); @@ -102,10 +102,10 @@ BigFloat SampleUniform( const BigFloat& a, const BigFloat& b ) template<> BigInt SampleUniform( const BigInt& a, const BigInt& b ) { - BigInt sample; + BigInt sample; gmp_randstate_t randState; mpfr::RandomState( randState ); - + mpz_urandomb( sample.Pointer(), randState, b.NumBits() ); return a+Mod(sample,b-a); } @@ -117,7 +117,7 @@ Int SampleUniform( const Int& a, const Int& b ) { #ifdef EL_HAVE_CXX11RANDOM std::mt19937& gen = Generator(); - std::uniform_int_distribution intDist(a,b-1); + std::uniform_int_distribution intDist(a,b-1); return intDist(gen); #else return a + (rand() % (b-a));