Commit a86863f4 authored by Berrill, Mark's avatar Berrill, Mark
Browse files

Updating miniapp

parent d0ee7b1c
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -6,8 +6,8 @@ rm -rf CMake*

cmake                                   \
   -D CMAKE_BUILD_TYPE=Release          \
   -D CMAKE_CXX_COMPILER=g++            \
   -D CXX_STD=11                        \
   -D CMAKE_CXX_COMPILER=mpic++         \
   -D CMAKE_CXX_STANDARD=11             \
   -D USE_OPENACC=0                     \
   -D USE_OPENMP=1                      \
   -D USE_KOKKOS=0                      \
+21 −12
Original line number Diff line number Diff line
@@ -104,7 +104,8 @@ int run_tests( const std::string &filename, const Options &options )
    // Call create_image for each method
    int N_errors = 0;
    std::this_thread::sleep_for( std::chrono::milliseconds( 50 ) );
    std::vector<std::vector<double>> time( methods.size() );
    std::vector<Times> perf1( methods.size() );
    std::vector<Times> perf2( methods.size() );
    for ( size_t i = 0; i < methods.size(); i++ ) {
        if ( rank() == 0 )
            std::cout << "  Running " << methods[i] << std::endl;
@@ -117,16 +118,19 @@ int run_tests( const std::string &filename, const Options &options )
            RayTrace::create_image( info2, methods[i] );
        // Run the timing tests
        auto t0 = std::chrono::steady_clock::now();
        std::vector<double> tmp1;
        std::vector<double> tmp2;
        while ( true ) {
            for ( int it = 0; it < iterations; it++ ) {
                auto t1 = std::chrono::steady_clock::now();
                // Run the calculation
                RayTrace::create_image( info, methods[i] );
                if ( options.benchmark ) {
                auto t2 = std::chrono::steady_clock::now();
                // Mimic communication in full application
                communicate( *info );
                }
                auto t2 = std::chrono::steady_clock::now();
                time[i].push_back( 1e-9 * diff_ns( t2, t1 ) );
                auto t3 = std::chrono::steady_clock::now();
                tmp1.push_back( 1e-9 * diff_ns( t2, t1 ) );
                tmp2.push_back( 1e-9 * diff_ns( t3, t1 ) );
                t1 = t2;
            }
            double time = 1e-9 * diff_ns( std::chrono::steady_clock::now(), t0 );
@@ -134,13 +138,18 @@ int run_tests( const std::string &filename, const Options &options )
            if ( time > options.time )
                break;
        }
        time[i] = gatherAll( time[i] );
        perf1[i] = Times( tmp2 );
        perf2[i] = Times( tmp2 );
        // Check the results
        if ( options.scale == 1.0 ) {
            bool pass = check_ans( image0, I_ang0, *info );
            if ( !pass )
                N_errors++;
        }
        if ( perf1[i].avg[0] < 0.5 * perf1[i].avg[1] ) {
            std::cout << "Slow rank detected: " << rank() << std::endl;
            N_errors++;
        }
        free( (void *) info->image );
        free( (void *) info->I_ang );
        info->image = nullptr;
@@ -148,7 +157,7 @@ int run_tests( const std::string &filename, const Options &options )
    }
    if ( rank() == 0 ) {
        if ( options.benchmark ) {
            double t = getAvg( time[0] );
            double t = perf2[0].avg[1];
            double N = 0;
            if ( info->seed_beam == nullptr ) {
                auto &beam = *( info->euv_beam );
@@ -162,10 +171,10 @@ int run_tests( const std::string &filename, const Options &options )
        } else {
            printf( "\n        METHOD    Avg     Min     Max   Std Dev\n" );
            for ( size_t i = 0; i < methods.size(); i++ ) {
                double min = getMin( time[i] );
                double max = getMax( time[i] );
                double avg = getAvg( time[i] );
                double dev = getDev( time[i] );
                double min = perf1[i].min[1];
                double max = perf1[i].max[1];
                double avg = perf1[i].avg[1];
                double dev = perf1[i].std[1];
                printf( "%14s %7.3f %7.3f %7.3f %7.3f\n", methods[i].c_str(), avg, min, max, dev );
                if ( dev / avg > 0.25 ) {
                    printf( "   Standard deviation exceeded tolerance (25%%)\n" );
+50 −27
Original line number Diff line number Diff line
@@ -205,37 +205,60 @@ void scale_problem( RayTrace::create_image_struct &info, double scale )


/**********************************************************************
 * Basic math operations                                               *
 * Compute the statistics for the times                                *
 **********************************************************************/
double getMin( const std::vector<double> &x )
Times::Times()
{
    double y = x[0];
    for ( size_t i = 1; i < x.size(); i++ )
        y = std::min( y, x[i] );
    return y;
}
double getMax( const std::vector<double> &x )
{
    double y = x[0];
    for ( size_t i = 1; i < x.size(); i++ )
        y = std::max( y, x[i] );
    return y;
}
double getAvg( const std::vector<double> &x )
    N[0]   = 0;
    N[1]   = 0;
    min[0] = 0;
    min[1] = 0;
    max[0] = 0;
    max[1] = 0;
    avg[0] = 0;
    avg[1] = 0;
    std[0] = 0;
    std[1] = 0;
}
Times::Times( const std::vector<double> &x )
{
    double y = 0;
    for ( size_t i = 0; i < x.size(); i++ )
        y += x[i];
    return y / x.size();
}
double getDev( const std::vector<double> &x )
{
    double avg = getAvg( x );
    double y   = 0;
    for ( size_t i = 0; i < x.size(); i++ )
        y += ( x[i] - avg ) * ( x[i] - avg );
    y = sqrt( y / x.size() );
    return y;
    // Compute local properties
    N[0]   = x.size();
    min[0] = 1e100;
    max[0] = 0;
    avg[0] = 0;
    for ( size_t i = 0; i < x.size(); i++ ) {
        min[0] = std::min( min[0], x[i] );
        max[0] = std::max( max[0], x[i] );
        avg[0] += x[i];
    }
    // Compute global properties
    N[1]   = N[0];
    min[1] = min[0];
    max[1] = max[0];
    avg[1] = avg[0];
#ifdef USE_MPI
    static_assert( sizeof( unsigned long long ) == sizeof( size_t ), "Unexpected size" );
    MPI_Allreduce( &N[0], &N[1], 1, MPI_UNSIGNED_LONG_LONG, MPI_SUM, MPI_COMM_WORLD );
    MPI_Allreduce( &min[0], &min[1], 1, MPI_DOUBLE, MPI_MIN, MPI_COMM_WORLD );
    MPI_Allreduce( &max[0], &max[1], 1, MPI_DOUBLE, MPI_MAX, MPI_COMM_WORLD );
    MPI_Allreduce( &avg[0], &avg[1], 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD );
#endif
    // Finish computing the average and the standard deviation
    avg[0] /= N[0];
    avg[1] /= N[1];
    std[0] = 0;
    std[1] = 0;
    for ( size_t i = 0; i < x.size(); i++ ) {
        std[0] += ( x[i] - avg[0] ) * ( x[i] - avg[0] );
        std[1] += ( x[i] - avg[1] ) * ( x[i] - avg[1] );
    }
#ifdef USE_MPI
    double tmp = std[1];
    MPI_Allreduce( &tmp, &std[1], 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD );
#endif
    std[0] = sqrt( std[0] / ( N[0] - 1 ) );
    std[1] = sqrt( std[1] / ( N[1] - 1 ) );
}


+29 −33
Original line number Diff line number Diff line
@@ -10,6 +10,35 @@
#include "RayTrace/RayTrace.h"


// Clas to hold options
class Options
{
public:
    Options();
    Options( int argc, char *argv[] );

public:
    bool benchmark = false;
    int iterations = 1;
    double scale   = 1.0;
    double time    = 0;
    std::vector<std::string> methods;
    std::vector<std::string> filenames;
};


// Class to store statistical information about the times
struct Times {
    size_t N[2];
    double min[2];
    double max[2];
    double avg[2];
    double std[2];
    Times();
    Times( const std::vector<double> &times );
};


// Function to print info about the hardware that we will use
void printHardware();

@@ -31,37 +60,4 @@ bool check_ans(
    const double *image0, const double *I_ang0, const RayTrace::create_image_struct &data );


// Get the minimum value
double getMin( const std::vector<double> &x );


// Get the maximum value
double getMax( const std::vector<double> &x );


// Get the average value
double getAvg( const std::vector<double> &x );


// Get the standard deviation
double getDev( const std::vector<double> &x );


// Clas to hold options
class Options
{
public:
    Options();
    Options( int argc, char *argv[] );

public:
    bool benchmark = false;
    int iterations = 1;
    double scale   = 1.0;
    double time    = 0;
    std::vector<std::string> methods;
    std::vector<std::string> filenames;
};


#endif

src/WriteCompilerFeatures.cmake

deleted100644 → 0
+0 −107
Original line number Diff line number Diff line
INCLUDE(CheckCXXCompilerFlag)
INCLUDE(CheckCXXSourceCompiles)


# CMake is adding extra options for extensions that we don't want
SET( CMAKE_CXX11_COMPILE_FEATURES -DDUMMY )
SET( CMAKE_CXX11_EXTENSION_COMPILE_OPTION -DDUMMY )
SET( CMAKE_CXX11_STANDARD_COMPILE_OPTION -DDUMMY )
SET( CMAKE_CXX14_COMPILE_FEATURES -DDUMMY )
SET( CMAKE_CXX14_EXTENSION_COMPILE_OPTION -DDUMMY )
SET( CMAKE_CXX14_STANDARD_COMPILE_OPTION -DDUMMY )
SET( CMAKE_CXX98_COMPILE_FEATURES -DDUMMY )
SET( CMAKE_CXX98_EXTENSION_COMPILE_OPTION -DDUMMY )
SET( CMAKE_CXX98_STANDARD_COMPILE_OPTION -DDUMMY )


# This function writes a list of the supported C++ compiler features
FUNCTION( WRITE_COMPILE_FEATURES FILENAME ${ARGN} )
    SET( PREFIX ${ARGN} )
    IF ( NOT PREFIX )
        SET( PREFIX " " )
    ELSE()
        SET( PREFIX "${PREFIX}_" )
    ENDIF()
    FILE(WRITE ${FILENAME} "// This is a automatically generated file to set define variables for supported C++ features\n" )
    TEST_FEATURE( SHARED_PTR ${FILENAME} ${PREFIX}
	    "#include <memory>
	     int main() {
	        std::shared_ptr<int> ptr;
	        return 0;
	     }"
    )
    TEST_FEATURE( STD_FUNCTION ${FILENAME} ${PREFIX}
	    "#include <functional>
         void myfun(int) { }
	     int main() {
            std::function<void(int)> f_display = myfun;
	        return 0;
	     }"
    )
    TEST_FEATURE( STD_TUPLE ${FILENAME} ${PREFIX}
	    "#include <tuple>
	     int main() {
            std::tuple<double,int> x(1,2);
	        return 0;
	     }"
    )
    TEST_FEATURE( VARIADIC_TEMPLATE ${FILENAME} ${PREFIX}
	    "#include <iostream>
         template<class... Ts> void test(Ts... ts) {}
	     int main() {
            test<int,double>(1,3);
	        return 0;
	     }"
    )
    IF ( USE_MATLAB )
        # Thread local storage and matlab do not agree
        FILE(APPEND ${FILENAME} "#define ${PREFIX}DISABLE_THREAD_LOCAL\n" )
    ELSE()
        TEST_FEATURE( THREAD_LOCAL ${FILENAME} ${PREFIX}
	        "#include <iostream>
             template<class... Ts> void test(Ts... ts) {}
	         int main() {
                thread_local static int id = 0;
	            return 0;
	         }"
        )
    ENDIF()
    TEST_FEATURE( MOVE_CONSTRUCTOR ${FILENAME} ${PREFIX}
	    "#include <iostream>
         struct st { int i; st(){} st(st&&){} private: st(st&); };
         st fun() { return st(); }
	     int main() {
            st tmp = fun();
	        return 0;
	     }"
    )
    TEST_FEATURE( STATIC_ASSERT ${FILENAME} ${PREFIX}
	    "#include <iostream>
	     int main() {
            static_assert(true,\"test\");
	        return 0;
	     }"
    )
ENDFUNCTION()


# This function trys to compile and then sets the appropriate macro
FUNCTION( TEST_FEATURE FEATURE_NAME FILENAME PREFIX CODE )
    IF ( ${CXX_STD} STREQUAL "98" )
        # Disable all features for 98
        SET( ${FEATURE_NAME} OFF )
    ELSEIF ( DISABLE_${FEATURE_NAME} )
        # Disable feature
        SET( ${FEATURE_NAME} OFF )
    ELSE()
        # Check if compiler allows feature
        SET( CMAKE_REQUIRED_FLAGS ${CMAKE_CXX_FLAGS} )
        CHECK_CXX_SOURCE_COMPILES( "${CODE}" ${FEATURE_NAME} )
    ENDIF()
    IF ( ${FEATURE_NAME} )
        FILE(APPEND ${FILENAME} "#define ${PREFIX}ENABLE_${FEATURE_NAME}\n" )
    ELSE()
        FILE(APPEND ${FILENAME} "#define ${PREFIX}DISABLE_${FEATURE_NAME}\n" )
    ENDIF()
ENDFUNCTION()