Updating StackTrace and improving performance converting uCT data

This commit is contained in:
Mark Berrill 2020-01-02 13:23:51 -05:00
parent 0006695d5f
commit 3c854fd002
11 changed files with 303 additions and 89 deletions

View File

@ -7,6 +7,7 @@
#include <algorithm> #include <algorithm>
#include <atomic> #include <atomic>
#include <cerrno>
#include <csignal> #include <csignal>
#include <cstring> #include <cstring>
#include <iostream> #include <iostream>
@ -348,8 +349,11 @@ static inline int exec3( const char *cmd, FUNCTION &fun )
if ( buffer[0] != 0 ) if ( buffer[0] != 0 )
fun( buffer ); fun( buffer );
} }
auto status = pclose( pipe ); int code = pclose( pipe );
int code = WEXITSTATUS( status ); if ( errno == ECHILD ) {
errno = 0;
code = 0;
}
std::this_thread::yield(); // Allow any signals to process std::this_thread::yield(); // Allow any signals to process
resetSignal( SIGCHLD ); // Clear child exited resetSignal( SIGCHLD ); // Clear child exited
return code; return code;
@ -1741,7 +1745,7 @@ std::vector<int> StackTrace::defaultSignalsToCatch()
* Set the signal handlers * * Set the signal handlers *
****************************************************************************/ ****************************************************************************/
static std::function<void( const StackTrace::abort_error &err )> abort_fun; static std::function<void( const StackTrace::abort_error &err )> abort_fun;
static StackTrace::abort_error rethrow() StackTrace::abort_error rethrow()
{ {
StackTrace::abort_error error; StackTrace::abort_error error;
#ifdef USE_LINUX #ifdef USE_LINUX
@ -1775,14 +1779,14 @@ static StackTrace::abort_error rethrow()
} }
return error; return error;
} }
static void term_func_abort( int sig ) void StackTrace::terminateFunctionSignal( int sig )
{ {
StackTrace::abort_error err; StackTrace::abort_error err;
err.type = StackTrace::terminateType::signal; err.type = StackTrace::terminateType::signal;
err.signal = sig; err.signal = sig;
err.bytes = StackTrace::Utilities::getMemoryUsage(); err.bytes = StackTrace::Utilities::getMemoryUsage();
err.stack = StackTrace::backtrace(); err.stack = StackTrace::backtrace();
err.stackType = StackTrace::printStackType::global; err.stackType = StackTrace::getDefaultStackType();
abort_fun( err ); abort_fun( err );
} }
static bool signals_set[256] = { false }; static bool signals_set[256] = { false };
@ -1829,7 +1833,7 @@ void StackTrace::setErrorHandler( std::function<void( const StackTrace::abort_er
{ {
abort_fun = abort; abort_fun = abort;
std::set_terminate( term_func ); std::set_terminate( term_func );
setSignals( defaultSignalsToCatch(), &term_func_abort ); setSignals( defaultSignalsToCatch(), &terminateFunctionSignal );
std::set_unexpected( term_func ); std::set_unexpected( term_func );
} }
void StackTrace::clearErrorHandler() void StackTrace::clearErrorHandler()
@ -2215,7 +2219,7 @@ void StackTrace::cleanupStackTrace( multi_stack_info &stack )
// Remove callstack (and all children) for threads that are just contributing // Remove callstack (and all children) for threads that are just contributing
bool test = function.find( "_callstack_signal_handler" ) != npos || bool test = function.find( "_callstack_signal_handler" ) != npos ||
function.find( "getGlobalCallStacks" ) != npos || function.find( "getGlobalCallStacks" ) != npos ||
function.find( "(" ) == npos; function.find( "backtrace" ) != npos || function.find( "(" ) == npos;
if ( test ) { if ( test ) {
it = stack.children.erase( it ); it = stack.children.erase( it );
continue; continue;
@ -2515,3 +2519,11 @@ const char *StackTrace::abort_error::what() const noexcept
d_msg.erase( i, 1 ); d_msg.erase( i, 1 );
return d_msg.c_str(); return d_msg.c_str();
} }
/****************************************************************************
* Get/Set default stack type *
****************************************************************************/
static StackTrace::printStackType abort_stackType = StackTrace::printStackType::global;
void StackTrace::setDefaultStackType( StackTrace::printStackType type ) { abort_stackType = type; }
StackTrace::printStackType StackTrace::getDefaultStackType() { return abort_stackType; }

View File

@ -246,6 +246,10 @@ void clearSignals();
void raiseSignal( int signal ); void raiseSignal( int signal );
//! Default function to abort after catching a signal
void terminateFunctionSignal( int signal );
//! Return a list of all signals that can be caught //! Return a list of all signals that can be caught
std::vector<int> allSignalsToCatch(); std::vector<int> allSignalsToCatch();
@ -289,6 +293,13 @@ multi_stack_info generateFromString( const std::vector<std::string> &str );
multi_stack_info generateFromString( const std::string &str ); multi_stack_info generateFromString( const std::string &str );
//! Set default stack type
void setDefaultStackType( StackTrace::printStackType );
//! Get default stack type
StackTrace::printStackType getDefaultStackType();
} // namespace StackTrace } // namespace StackTrace

View File

@ -8,8 +8,10 @@
#include <cstring> #include <cstring>
#include <fstream> #include <fstream>
#include <iostream> #include <iostream>
#include <mutex>
#include <sstream> #include <sstream>
#include <stdexcept> #include <stdexcept>
#include <typeinfo>
#ifdef USE_MPI #ifdef USE_MPI
#include "mpi.h" #include "mpi.h"
@ -19,6 +21,10 @@
#include "MemoryApp.h" #include "MemoryApp.h"
#endif #endif
#ifdef USE_GCOV
extern "C" void __gcov_flush( void );
#endif
#define perr std::cerr #define perr std::cerr
@ -65,6 +71,12 @@
// clang-format on // clang-format on
#ifdef __GNUC__
#define USE_ABI
#include <cxxabi.h>
#endif
namespace StackTrace { namespace StackTrace {
@ -96,13 +108,12 @@ inline size_t findfirst( const std::vector<TYPE> &X, TYPE Y )
/**************************************************************************** /****************************************************************************
* Function to terminate the program * * Function to terminate the program *
****************************************************************************/ ****************************************************************************/
static bool abort_throwException = false; static bool abort_throwException = false;
static printStackType abort_stackType = printStackType::global; static int force_exit = 0;
static int force_exit = 0;
void Utilities::setAbortBehavior( bool throwException, int stackType ) void Utilities::setAbortBehavior( bool throwException, int stackType )
{ {
abort_throwException = throwException; abort_throwException = throwException;
abort_stackType = static_cast<printStackType>( stackType ); StackTrace::setDefaultStackType( static_cast<printStackType>( stackType ) );
} }
void Utilities::abort( const std::string &message, const std::string &filename, const int line ) void Utilities::abort( const std::string &message, const std::string &filename, const int line )
{ {
@ -112,16 +123,28 @@ void Utilities::abort( const std::string &message, const std::string &filename,
err.type = terminateType::abort; err.type = terminateType::abort;
err.line = line; err.line = line;
err.bytes = Utilities::getMemoryUsage(); err.bytes = Utilities::getMemoryUsage();
err.stackType = abort_stackType; err.stackType = StackTrace::getDefaultStackType();
err.stack = StackTrace::backtrace(); err.stack = StackTrace::backtrace();
throw err; throw err;
} }
static void terminate( const StackTrace::abort_error &err ) static std::mutex terminate_mutex;
static inline void callAbort()
{ {
#ifdef USE_GCOV
__gcov_flush();
#endif
terminate_mutex.unlock();
std::abort();
}
void Utilities::terminate( const StackTrace::abort_error &err )
{
// Lock mutex to ensure multiple threads do not try to abort simultaneously
terminate_mutex.lock();
// Clear the error handlers
clearErrorHandler(); clearErrorHandler();
// Print the message and abort // Print the message and abort
if ( force_exit > 1 ) { if ( force_exit > 1 ) {
std::abort(); callAbort();
} else if ( !abort_throwException ) { } else if ( !abort_throwException ) {
// Use MPI_abort (will terminate all processes) // Use MPI_abort (will terminate all processes)
force_exit = 2; force_exit = 2;
@ -135,10 +158,11 @@ static void terminate( const StackTrace::abort_error &err )
MPI_Abort( MPI_COMM_WORLD, -1 ); MPI_Abort( MPI_COMM_WORLD, -1 );
} }
#endif #endif
std::abort(); callAbort();
} else { } else {
perr << err.what(); perr << err.what();
std::abort(); perr.flush();
callAbort();
} }
} }
@ -149,7 +173,7 @@ static void terminate( const StackTrace::abort_error &err )
static void setTerminateErrorHandler() static void setTerminateErrorHandler()
{ {
// Set the terminate routine for runtime errors // Set the terminate routine for runtime errors
StackTrace::setErrorHandler( terminate ); StackTrace::setErrorHandler( Utilities::terminate );
} }
void Utilities::setErrorHandlers() void Utilities::setErrorHandlers()
{ {
@ -293,4 +317,18 @@ std::string Utilities::exec( const string_view &cmd, int &exit_code )
} }
/****************************************************************************
* Get the type name *
****************************************************************************/
std::string Utilities::getTypeName( const std::type_info &id )
{
std::string name = id.name();
#if defined( USE_ABI )
int status;
name = abi::__cxa_demangle( name.c_str(), 0, 0, &status );
#endif
return name;
}
} // namespace StackTrace } // namespace StackTrace

View File

@ -4,6 +4,7 @@
#include <stdexcept> #include <stdexcept>
#include <string> #include <string>
#include <thread> #include <thread>
#include <typeinfo>
#include "StackTrace/StackTrace.h" #include "StackTrace/StackTrace.h"
#include "StackTrace/string_view.h" #include "StackTrace/string_view.h"
@ -28,9 +29,14 @@ void abort( const std::string &message, const std::string &filename, const int l
void setAbortBehavior( bool throwException, int stackType = 2 ); void setAbortBehavior( bool throwException, int stackType = 2 );
//! Function to terminate the application
void terminate( const StackTrace::abort_error &err );
//! Function to set the error handlers //! Function to set the error handlers
void setErrorHandlers(); void setErrorHandlers();
//! Function to clear the error handlers //! Function to clear the error handlers
void clearErrorHandlers(); void clearErrorHandlers();
@ -92,6 +98,18 @@ void cause_segfault();
std::string exec( const StackTrace::string_view &cmd, int &exit_code ); std::string exec( const StackTrace::string_view &cmd, int &exit_code );
//! Return the hopefully demangled name of the given type
std::string getTypeName( const std::type_info &id );
//! Return the hopefully demangled name of the given type
template<class TYPE>
inline std::string getTypeName()
{
return getTypeName( typeid( TYPE ) );
}
} // namespace Utilities } // namespace Utilities
} // namespace StackTrace } // namespace StackTrace

View File

@ -119,7 +119,7 @@ public:
int result = 0; int result = 0;
for ( int i = 0; i < N && result == 0; i++ ) for ( int i = 0; i < N && result == 0; i++ )
if ( d_data[i] != other[i] ) if ( d_data[i] != other[i] )
result = d_data[i] < other[i] ? -i : i; result = d_data[i] < other[i] ? -( i + 1 ) : ( i + 1 );
if ( result == 0 ) if ( result == 0 )
result = size() == other.size() ? 0 : size() < other.size() ? -1 : 1; result = size() == other.size() ? 0 : size() < other.size() ? -1 : 1;
return result; return result;

View File

@ -767,6 +767,8 @@ void runAnalysis::run(int timestep, std::shared_ptr<Database> input_db, TwoPhase
double *Pressure, double *Velocity, double *fq, double *Den) double *Pressure, double *Velocity, double *fq, double *Den)
{ {
int N = d_N[0]*d_N[1]*d_N[2]; int N = d_N[0]*d_N[1]*d_N[2];
NULL_USE( N );
NULL_USE( Phi );
auto db = input_db->getDatabase( "Analysis" ); auto db = input_db->getDatabase( "Analysis" );
//int timestep = db->getWithDefault<int>( "timestep", 0 ); //int timestep = db->getWithDefault<int>( "timestep", 0 );
@ -937,8 +939,6 @@ void runAnalysis::run(int timestep, std::shared_ptr<Database> input_db, TwoPhase
******************************************************************/ ******************************************************************/
void runAnalysis::basic(int timestep, std::shared_ptr<Database> input_db, SubPhase &Averages, const double *Phi, double *Pressure, double *Velocity, double *fq, double *Den) void runAnalysis::basic(int timestep, std::shared_ptr<Database> input_db, SubPhase &Averages, const double *Phi, double *Pressure, double *Velocity, double *fq, double *Den)
{ {
int N = d_N[0]*d_N[1]*d_N[2];
// Check which analysis steps we need to perform // Check which analysis steps we need to perform
auto color_db = input_db->getDatabase( "Color" ); auto color_db = input_db->getDatabase( "Color" );
auto vis_db = input_db->getDatabase( "Visualization" ); auto vis_db = input_db->getDatabase( "Visualization" );
@ -954,7 +954,7 @@ void runAnalysis::basic(int timestep, std::shared_ptr<Database> input_db, SubPha
finish(); finish();
} }
PROFILE_START("run"); PROFILE_START("basic");
// Copy the appropriate variables to the host (so we can spawn new threads) // Copy the appropriate variables to the host (so we can spawn new threads)
ScaLBL_DeviceBarrier(); ScaLBL_DeviceBarrier();
@ -983,7 +983,6 @@ void runAnalysis::basic(int timestep, std::shared_ptr<Database> input_db, SubPha
} }
PROFILE_STOP("Copy data to host"); PROFILE_STOP("Copy data to host");
PROFILE_START("run",1);
// Spawn threads to do the analysis work // Spawn threads to do the analysis work
//if (timestep%d_restart_interval==0){ //if (timestep%d_restart_interval==0){
// if ( matches(type,AnalysisType::ComputeAverages) ) { // if ( matches(type,AnalysisType::ComputeAverages) ) {
@ -1036,12 +1035,11 @@ void runAnalysis::basic(int timestep, std::shared_ptr<Database> input_db, SubPha
d_wait_vis = d_tpool.add_work(work); d_wait_vis = d_tpool.add_work(work);
} }
PROFILE_STOP("run"); PROFILE_STOP("basic");
} }
void runAnalysis::WriteVisData(int timestep, std::shared_ptr<Database> input_db, SubPhase &Averages, const double *Phi, double *Pressure, double *Velocity, double *fq, double *Den) void runAnalysis::WriteVisData(int timestep, std::shared_ptr<Database> input_db, SubPhase &Averages, const double *Phi, double *Pressure, double *Velocity, double *fq, double *Den)
{ {
int N = d_N[0]*d_N[1]*d_N[2];
auto color_db = input_db->getDatabase( "Color" ); auto color_db = input_db->getDatabase( "Color" );
auto vis_db = input_db->getDatabase( "Visualization" ); auto vis_db = input_db->getDatabase( "Visualization" );
//int timestep = color_db->getWithDefault<int>( "timestep", 0 ); //int timestep = color_db->getWithDefault<int>( "timestep", 0 );
@ -1068,7 +1066,6 @@ void runAnalysis::WriteVisData(int timestep, std::shared_ptr<Database> input_db,
d_wait_vis = d_tpool.add_work(work2); d_wait_vis = d_tpool.add_work(work2);
//Averages.WriteVis = false; //Averages.WriteVis = false;
// }
PROFILE_STOP("write vis"); PROFILE_STOP("write vis");
} }

View File

@ -44,9 +44,9 @@ Array<TYPE> redistribute( const RankInfoStruct& src_rank, const Array<TYPE>& src
if ( !src_data.empty() ) { if ( !src_data.empty() ) {
int i1[3] = { src_size[0] * src_rank.ix, src_size[1] * src_rank.jy, src_size[2] * src_rank.kz }; int i1[3] = { src_size[0] * src_rank.ix, src_size[1] * src_rank.jy, src_size[2] * src_rank.kz };
int i2[3] = { i1[0] + src_size[0] - 1, i1[1] + src_size[1] - 1, i1[2] + src_size[2] - 1 }; int i2[3] = { i1[0] + src_size[0] - 1, i1[1] + src_size[1] - 1, i1[2] + src_size[2] - 1 };
for ( size_t i=0; i<dst_rank.nx; i++ ) { for ( int i=0; i<dst_rank.nx; i++ ) {
for ( size_t j=0; j<dst_rank.ny; j++ ) { for ( int j=0; j<dst_rank.ny; j++ ) {
for ( size_t k=0; k<dst_rank.nz; k++ ) { for ( int k=0; k<dst_rank.nz; k++ ) {
int j1[3] = { i * dst_size[0], j * dst_size[1], k * dst_size[2] }; int j1[3] = { i * dst_size[0], j * dst_size[1], k * dst_size[2] };
int j2[3] = { j1[0] + dst_size[0] - 1, j1[1] + dst_size[1] - 1, j1[2] + dst_size[2] - 1 }; int j2[3] = { j1[0] + dst_size[0] - 1, j1[1] + dst_size[1] - 1, j1[2] + dst_size[2] - 1 };
auto index = calcOverlap( i1, i2, j1, j2 ); auto index = calcOverlap( i1, i2, j1, j2 );
@ -65,9 +65,9 @@ Array<TYPE> redistribute( const RankInfoStruct& src_rank, const Array<TYPE>& src
Array<TYPE> dst_data( dst_size[0], dst_size[1], dst_size[2] ); Array<TYPE> dst_data( dst_size[0], dst_size[1], dst_size[2] );
int i1[3] = { dst_size[0] * dst_rank.ix, dst_size[1] * dst_rank.jy, dst_size[2] * dst_rank.kz }; int i1[3] = { dst_size[0] * dst_rank.ix, dst_size[1] * dst_rank.jy, dst_size[2] * dst_rank.kz };
int i2[3] = { i1[0] + dst_size[0] - 1, i1[1] + dst_size[1] - 1, i1[2] + dst_size[2] - 1 }; int i2[3] = { i1[0] + dst_size[0] - 1, i1[1] + dst_size[1] - 1, i1[2] + dst_size[2] - 1 };
for ( size_t i=0; i<src_rank.nx; i++ ) { for ( int i=0; i<src_rank.nx; i++ ) {
for ( size_t j=0; j<src_rank.ny; j++ ) { for ( int j=0; j<src_rank.ny; j++ ) {
for ( size_t k=0; k<src_rank.nz; k++ ) { for ( int k=0; k<src_rank.nz; k++ ) {
int j1[3] = { i * src_size[0], j * src_size[1], k * src_size[2] }; int j1[3] = { i * src_size[0], j * src_size[1], k * src_size[2] };
int j2[3] = { j1[0] + src_size[0] - 1, j1[1] + src_size[1] - 1, j1[2] + src_size[2] - 1 }; int j2[3] = { j1[0] + src_size[0] - 1, j1[1] + src_size[1] - 1, j1[2] + src_size[2] - 1 };
auto index = calcOverlap( i1, i2, j1, j2 ); auto index = calcOverlap( i1, i2, j1, j2 );

View File

@ -70,8 +70,6 @@ Array<uint8_t> readMicroCT( const Database& domain, MPI_Comm comm )
auto n = domain.getVector<int>( "n" ); auto n = domain.getVector<int>( "n" );
int rank = comm_rank(MPI_COMM_WORLD); int rank = comm_rank(MPI_COMM_WORLD);
auto nproc = domain.getVector<int>( "nproc" ); auto nproc = domain.getVector<int>( "nproc" );
auto ReadValues = domain.getVector<int>( "ReadValues" );
auto WriteValues = domain.getVector<int>( "WriteValues" );
RankInfoStruct rankInfo( rank, nproc[0], nproc[1], nproc[2] ); RankInfoStruct rankInfo( rank, nproc[0], nproc[1], nproc[2] );
// Determine the largest file number to get // Determine the largest file number to get
@ -95,29 +93,26 @@ Array<uint8_t> readMicroCT( const Database& domain, MPI_Comm comm )
ERROR( "Invalid name for first file" ); ERROR( "Invalid name for first file" );
} }
data = readMicroCT( filename ); data = readMicroCT( filename );
// Relabel the data
for (int k = 0; k<1024; k++){
for (int j = 0; j<1024; j++){
for (int i = 0; i<1024; i++){
//n = k*Nfx*Nfy + j*Nfx + i;
//char locval = loc_id[n];
char locval = data(i,j,k);
for (int idx=0; idx<ReadValues.size(); idx++){
signed char oldvalue=ReadValues[idx];
signed char newvalue=WriteValues[idx];
if (locval == oldvalue){
data(i,j,k) = newvalue;
idx = ReadValues.size();
}
}
}
}
}
} }
// Redistribute the data // Redistribute the data
data = redistribute( srcRankInfo, data, rankInfo, { n[0], n[1], n[2] }, comm ); data = redistribute( srcRankInfo, data, rankInfo, { n[0], n[1], n[2] }, comm );
// Relabel the data
auto ReadValues = domain.getVector<int>( "ReadValues" );
auto WriteValues = domain.getVector<int>( "WriteValues" );
ASSERT( ReadValues.size() == WriteValues.size() );
int readMaxValue = 0;
for ( auto v : ReadValues )
readMaxValue = std::max( data.max()+1, v );
std::vector<int> map( readMaxValue + 1, -1 );
for ( size_t i=0; i<ReadValues.size(); i++ )
map[ReadValues[i]] = WriteValues[i];
for ( size_t i=0; i<data.length(); i++ ) {
int t = data(i);
ASSERT( t >= 0 && t <= readMaxValue );
data(i) = map[t];
}
return data; return data;
} }

View File

@ -1,10 +1,116 @@
#include "common/Utilities.h" #include "common/Utilities.h"
#include "StackTrace/StackTrace.h"
#include "StackTrace/ErrorHandlers.h"
#ifdef USE_TIMER
#include "MemoryApp.h"
#include "ProfilerApp.h"
#endif
#ifdef USE_MPI
#include "mpi.h"
#endif
#include <math.h>
#include <algorithm> #include <algorithm>
#include <math.h>
#include <mutex>
// Factor a number into it's prime factors // Mutex for Utility functions
static std::mutex Utilities_mutex;
/****************************************************************************
* Function to perform the default startup/shutdown sequences *
****************************************************************************/
void Utilities::startup( int argc, char **argv )
{
NULL_USE( argc );
NULL_USE( argv );
// Disable OpenMP
Utilities::setenv( "OMP_NUM_THREADS", "1" );
Utilities::setenv( "MKL_NUM_THREADS", "1" );
// Start MPI
#ifdef USE_MPI
int provided;
MPI_Init_thread( &argc, &argv, MPI_THREAD_MULTIPLE, &provided );
if ( provided < MPI_THREAD_MULTIPLE ) {
int rank;
MPI_Comm_rank( MPI_COMM_WORLD, &rank );
if ( rank == 0 )
std::cerr << "Warning: Failed to start MPI with necessary thread support, thread support will be disabled" << std::endl;
}
StackTrace::globalCallStackInitialize( MPI_COMM_WORLD );
#endif
// Set the error handlers
Utilities::setAbortBehavior( true, 3 );
Utilities::setErrorHandlers();
}
void Utilities::shutdown()
{
// Clear the error handlers
Utilities::clearErrorHandlers();
StackTrace::clearSignals();
StackTrace::clearSymbols();
int rank = 0;
#ifdef USE_MPI
MPI_Comm_rank( MPI_COMM_WORLD, &rank );
StackTrace::globalCallStackFinalize();
MPI_Barrier( MPI_COMM_WORLD );
MPI_Finalize();
#endif
#ifdef USE_TIMER
PROFILE_DISABLE();
auto memory = MemoryApp::getMemoryStats();
if ( rank == 0 && memory.N_new > memory.N_delete )
MemoryApp::print( std::cout );
#endif
}
/****************************************************************************
* Function to set an environemental variable *
****************************************************************************/
void Utilities::setenv( const std::string &name, const std::string &value )
{
Utilities_mutex.lock();
#if defined( USE_LINUX ) || defined( USE_MAC )
bool pass = false;
if ( !value.empty() )
pass = ::setenv( name.data(), value.data(), 1 ) == 0;
else
pass = ::unsetenv( name.data() ) == 0;
#elif defined( USE_WINDOWS )
bool pass = SetEnvironmentVariable( name.data(), value.data() ) != 0;
#else
#error Unknown OS
#endif
Utilities_mutex.unlock();
if ( !pass ) {
char msg[1024];
if ( !value.empty() )
sprintf(
msg, "Error setting enviornmental variable: %s=%s\n", name.data(), value.data() );
else
sprintf( msg, "Error clearing enviornmental variable: %s\n", name.data() );
ERROR( msg );
}
}
std::string Utilities::getenv( const std::string &name )
{
std::string var;
Utilities_mutex.lock();
auto tmp = std::getenv( name.data() );
if ( tmp )
var = std::string( tmp );
Utilities_mutex.unlock();
return var;
}
/****************************************************************************
* Factor a number into it's prime factors *
****************************************************************************/
std::vector<int> Utilities::factor(size_t number) std::vector<int> Utilities::factor(size_t number)
{ {
if ( number<=3 ) if ( number<=3 )
@ -54,9 +160,13 @@ std::vector<int> Utilities::factor(size_t number)
} }
// Dummy function to prevent compiler from optimizing away variable /****************************************************************************
* Dummy function to prevent compiler from optimizing away variable *
****************************************************************************/
void Utilities::nullUse( void* data ) void Utilities::nullUse( void* data )
{ {
NULL_USE(data); NULL_USE(data);
} }

View File

@ -25,6 +25,37 @@ using StackTrace::Utilities::sleep_ms;
using StackTrace::Utilities::sleep_s; using StackTrace::Utilities::sleep_s;
/*!
* \brief Start MPI, error handlers
* \details This routine will peform the default startup sequence
* \param argc argc from main
* \param argv argv from main
*/
void startup( int argc, char **argv );
/*!
* \brief Stop MPI, error handlers
* \details This routine will peform the default shutdown sequence to match startup
*/
void shutdown();
/*!
* Get an environmental variable
* @param name The name of the environmental variable
* @return The value of the enviornmental variable
*/
std::string getenv( const std::string &name );
/*!
* Set an environmental variable
* @param name The name of the environmental variable
* @param value The value to set
*/
void setenv( const std::string &name, const std::string &value );
//! std::string version of sprintf //! std::string version of sprintf
inline std::string stringf( const char *format, ... ); inline std::string stringf( const char *format, ... );

View File

@ -7,6 +7,7 @@
#include <fstream> #include <fstream>
#include "models/ColorModel.h" #include "models/ColorModel.h"
#include "common/Utilities.h"
//#define WRE_SURFACES //#define WRE_SURFACES
@ -15,7 +16,6 @@
* James E. McClure 2013-2014 * James E. McClure 2013-2014
*/ */
using namespace std;
//************************************************************************* //*************************************************************************
// Implementation of Two-Phase Immiscible LBM using CUDA // Implementation of Two-Phase Immiscible LBM using CUDA
@ -23,27 +23,26 @@ using namespace std;
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
// Initialize MPI // Initialize MPI and error handlers
int provided_thread_support = -1; Utilities::startup( argc, argv );
MPI_Init_thread(&argc,&argv,MPI_THREAD_MULTIPLE,&provided_thread_support);
MPI_Comm comm;
MPI_Comm_dup(MPI_COMM_WORLD,&comm);
int rank = comm_rank(comm);
int nprocs = comm_size(comm);
if ( rank==0 && provided_thread_support<MPI_THREAD_MULTIPLE )
std::cerr << "Warning: Failed to start MPI with necessary thread support, thread support will be disabled" << std::endl;
{ // Limit scope so variables that contain communicators will free before MPI_Finialize { // Limit scope so variables that contain communicators will free before MPI_Finialize
if (rank == 0){ MPI_Comm comm;
printf("********************************************************\n"); MPI_Comm_dup(MPI_COMM_WORLD,&comm);
printf("Running Color LBM \n"); int rank = comm_rank(comm);
printf("********************************************************\n"); int nprocs = comm_size(comm);
}
// Initialize compute device if (rank == 0){
int device=ScaLBL_SetDevice(rank); printf("********************************************************\n");
ScaLBL_DeviceBarrier(); printf("Running Color LBM \n");
MPI_Barrier(comm); printf("********************************************************\n");
}
// Initialize compute device
ScaLBL_SetDevice(rank);
ScaLBL_DeviceBarrier();
MPI_Barrier(comm);
PROFILE_ENABLE(1); PROFILE_ENABLE(1);
//PROFILE_ENABLE_TRACE(); //PROFILE_ENABLE_TRACE();
//PROFILE_ENABLE_MEMORY(); //PROFILE_ENABLE_MEMORY();
@ -51,23 +50,26 @@ int main(int argc, char **argv)
PROFILE_START("Main"); PROFILE_START("Main");
Utilities::setErrorHandlers(); Utilities::setErrorHandlers();
auto filename = argv[1]; auto filename = argv[1];
ScaLBL_ColorModel ColorModel(rank,nprocs,comm); ScaLBL_ColorModel ColorModel(rank,nprocs,comm);
ColorModel.ReadParams(filename); ColorModel.ReadParams(filename);
ColorModel.SetDomain(); ColorModel.SetDomain();
ColorModel.ReadInput(); ColorModel.ReadInput();
ColorModel.Create(); // creating the model will create data structure to match the pore structure and allocate variables ColorModel.Create(); // creating the model will create data structure to match the pore structure and allocate variables
ColorModel.Initialize(); // initializing the model will set initial conditions for variables ColorModel.Initialize(); // initializing the model will set initial conditions for variables
ColorModel.Run(); ColorModel.Run();
//ColorModel.WriteDebug(); //ColorModel.WriteDebug();
PROFILE_STOP("Main"); PROFILE_STOP("Main");
PROFILE_SAVE("lbpm_color_simulator",1); PROFILE_SAVE("lbpm_color_simulator",1);
// **************************************************** // ****************************************************
MPI_Barrier(comm);
MPI_Barrier(comm);
MPI_Comm_free(&comm);
} // Limit scope so variables that contain communicators will free before MPI_Finialize } // Limit scope so variables that contain communicators will free before MPI_Finialize
MPI_Comm_free(&comm);
MPI_Finalize(); Utilities::shutdown();
} }