blob: 3bd09b55e77014778461e81957f81ebea145317e [file] [log] [blame]
//
// See README-LCALS_license.txt for access and distribution restrictions
//
//
// Header file with macros and constants for data types, execution,
// timing options, etc. used in LCALS
//
#ifndef LCALSParams_HXX
#define LCALSParams_HXX
////////////////////////////////////////////////////////////////////////////////
//
// This file contains various parameters that control compilation and some
// aspects of execution of the loop suite. The macro constants and typedefs in
// this file provide the ability to make changes that will propagate
// throughout the LCALS code when compiled. Parameters in this file specify:
//
// o Timing and checksum output options
// o Scalar data types and pointer types (e.g., restrict & alignment properties)
// o Loop variants that can be built by each compiler
// o Loop execution policies for traversal templates (used with loop bodies
// represented as lambda expressions or functors)
//
//
// IMPORTANT: MANY OF THE MACROS CONTROLLING THESE OPTIONS
// ARE SET IN THE LCALS_rules.mk FILE.
//
////////////////////////////////////////////////////////////////////////////////
#if defined(LCALS_VERIFY_CHECKSUM_ABBREVIATED)
static const int num_checksum_suite_passes = 1;
static const int num_checksum_samples = 3;
#endif
////////////////////////////////////////////////////////////////////////////////
//
// Define/undefine macro constants and other paramters used to control data
// type definitions.
//
////////////////////////////////////////////////////////////////////////////////
//
// Parameterized scalar data types.
//
typedef int Index_type;
#if defined(LCALS_USE_DOUBLE)
///
typedef double Real_type;
#elif defined(LCALS_USE_FLOAT)
///
typedef float Real_type;
#else
#error LCALS Real_type is undefined!
#endif
#include<complex>
typedef std::complex<Real_type> Complex_type;
//
// Use volatile keyword on loop variable for sampling loops to prevent
// compilers from potentially optimizing out loops where result is
// identical for each sample iteration.
//
typedef volatile int SampIndex_type;
//
// Use unsigned long for loop variable used in loops to flush cache to
// allow for large caches with size possibly bigger than what int can adderss.
//
typedef unsigned long CacheIndex_type;
//
// Floating point array data alignmnent value. Typically, same as
// SIMD vector width.
//
const int LCALS_DATA_ALIGN = 32;
//
// Compiler-specific definitions for inline directives, data alignment
// intrinsics, and SIMD vector pragmas
//
// Variables for compiler instrinsics, directives, typedefs
//
// LCALS_INLINE - macro to enforce method inlining
//
// LCALS_ALIGN_DATA(<variable>) - macro to express alignment of data,
// loop bounds, etc.
//
// LCALS_SIMD - macro to express SIMD vectorization pragma to force
// loop vectorization
//
#if defined(LCALS_COMPILER_ICC)
//
// Configuration options for Intel compilers
//
#define LCALS_INLINE inline __attribute__((always_inline))
#if __ICC < 1300 // use alignment intrinsic
#define LCALS_ALIGN_DATA(d) __assume_aligned(d, LCALS_DATA_ALIGN)
#else
#define LCALS_ALIGN_DATA(d) // TODO: Define this...
#endif
#define LCALS_SIMD // TODO: Define this...
#elif defined(LCALS_COMPILER_GNU)
//
// Configuration options for GNU compilers
//
#define LCALS_INLINE inline __attribute__((always_inline))
#define LCALS_ALIGN_DATA(d) __builtin_assume_aligned(d, LCALS_DATA_ALIGN)
#define LCALS_SIMD // TODO: Define this...
#elif defined(LCALS_COMPILER_XLC12)
//
// Configuration options for xlc v12 compiler (i.e., bgq/sequoia).
//
#define LCALS_INLINE inline __attribute__((always_inline))
#define LCALS_ALIGN_DATA(d) __alignx(LCALS_DATA_ALIGN, d)
//#define LCALS_SIMD _Pragma("simd_level(10)")
#define LCALS_SIMD // TODO: Define this...
#elif defined(LCALS_COMPILER_CLANG)
//
// Configuration options for clang compilers
//
#define LCALS_INLINE inline __attribute__((always_inline))
#define LCALS_ALIGN_DATA(d) // TODO: Define this...
#define LCALS_SIMD // TODO: Define this...
#else
#error LCALS compiler is undefined!
#endif
////////////////////////////////////////////////////////////////////////////////
//
// The following items include some setup items for pointer type definitions
// that follow.
//
////////////////////////////////////////////////////////////////////////////////
#if defined(LCALS_COMPILER_ICC)
//
// alignment attribute supported for versions > 12
//
#if __ICC >= 1300
typedef Real_type* __restrict__ __attribute__((align_value(LCALS_DATA_ALIGN))) TDRAReal_ptr;
typedef const Real_type* __restrict__ __attribute__((align_value(LCALS_DATA_ALIGN))) const_TDRAReal_ptr;
#endif
#elif defined(LCALS_COMPILER_GNU)
//
// Nothing here for now because alignment attribute is not working...
//
#elif defined(LCALS_COMPILER_XLC12)
extern
#ifdef __cplusplus
"builtin"
#endif
void __alignx(int n, const void* addr);
#elif defined(LCALS_COMPILER_CLANG)
typedef Real_type aligned_real_type __attribute__((aligned (LCALS_DATA_ALIGN)));
typedef aligned_real_type* __restrict__ TDRAReal_ptr;
typedef const aligned_real_type* __restrict__ const_TDRAReal_ptr;
#else
#error LCALS compiler is undefined!
#endif
#if defined(LCALS_USE_PTR_CLASS)
/*!
******************************************************************************
*
* \brief Class representing a restricted Real_type const pointer.
*
******************************************************************************
*/
class ConstRestrictRealPtr
{
public:
///
/// Ctors and assignment op.
///
ConstRestrictRealPtr() : dptr(0) { ; }
ConstRestrictRealPtr(const Real_type* d) : dptr(d) { ; }
ConstRestrictRealPtr& operator=(const Real_type* d) {
ConstRestrictRealPtr copy(d);
std::swap(dptr, copy.dptr);
return *this;
}
///
/// NOTE: Using compiler-generated copy ctor, dtor, and copy assignment op.
///
///
/// Implicit conversion operator to bare const pointer.
///
operator const Real_type*() { return dptr; }
///
/// "Explicit conversion operator" to bare const pointer,
/// consistent with boost shared ptr.
///
const Real_type* get() const { return dptr; }
///
/// Bracket operator.
///
const Real_type& operator [] (Index_type i) const
{
return( (const Real_type* __restrict__) dptr)[i];
}
///
/// + operator for pointer arithmetic.
///
const Real_type* operator+ (Index_type i) const { return dptr+i; }
private:
const Real_type* dptr;
};
/*!
******************************************************************************
*
* \brief Class representing a restricted Real_type (non-const) pointer.
*
******************************************************************************
*/
class RestrictRealPtr
{
public:
///
/// Ctors and assignment op.
///
RestrictRealPtr() : dptr(0) { ; }
RestrictRealPtr(Real_type* d) : dptr(d) { ; }
RestrictRealPtr& operator=(Real_type* d) {
RestrictRealPtr copy(d);
std::swap(dptr, copy.dptr);
return *this;
}
///
/// NOTE: Using compiler-generated copy ctor, dtor, and copy assignment op.
///
///
/// Implicit conversion operator to (non-const) bare pointer.
///
operator Real_type*() { return dptr; }
///
/// Implicit conversion operator to const bare pointer.
///
operator const Real_type*() const { return dptr; }
///
/// "Explicit conversion operator" to (non-const) bare pointer,
/// consistent with boost shared ptr.
///
Real_type* get() { return dptr; }
///
/// "Explicit conversion operator" to const bare pointer,
/// consistent with boost shared ptr.
///
const Real_type* get() const { return dptr; }
///
/// Operator that enables implicit conversion from RestrictRealPtr to
/// RestrictRealConstPtr.
///
operator ConstRestrictRealPtr ()
{ return ConstRestrictRealPtr(dptr); }
///
/// Bracket operator.
///
Real_type& operator [] (Index_type i)
{
return( (Real_type* __restrict__) dptr)[i];
}
///
/// + operator for (non-const) pointer arithmetic.
///
Real_type* operator+ (Index_type i) { return dptr+i; }
///
/// + operator for const pointer arithmetic.
///
const Real_type* operator+ (Index_type i) const { return dptr+i; }
private:
Real_type* dptr;
};
/*!
******************************************************************************
*
* \brief Class representing a restricted aligned Real_type const pointer.
*
******************************************************************************
*/
class ConstRestrictAlignedRealPtr
{
public:
///
/// Ctors and assignment op.
///
ConstRestrictAlignedRealPtr() : dptr(0) { ; }
ConstRestrictAlignedRealPtr(const Real_type* d) : dptr(d) { ; }
ConstRestrictAlignedRealPtr& operator=(const Real_type* d) {
ConstRestrictAlignedRealPtr copy(d);
std::swap(dptr, copy.dptr);
return *this;
}
///
/// NOTE: Using compiler-generated copy ctor, dtor, and copy assignment op.
///
///
/// Implicit conversion operator to bare const pointer.
///
operator const Real_type*() { return dptr; }
///
/// "Explicit conversion operator" to bare const pointer,
/// consistent with boost shared ptr.
///
const Real_type* get() const { return dptr; }
///
/// Compiler-specific bracket operators.
///
#if defined(LCALS_COMPILER_ICC)
///
const Real_type& operator [] (Index_type i) const
{
#if __ICC < 1300 // use alignment intrinsic
LCALS_ALIGN_DATA(dptr);
return( (const Real_type* __restrict__) dptr)[i];
#else // use alignment attribute
return( (const_TDRAReal_ptr) dptr)[i];
#endif
}
#elif defined(LCALS_COMPILER_GNU)
///
const Real_type& operator [] (Index_type i) const
{
#if 1 // NOTE: alignment instrinsic not available for older GNU compilers
return( (const Real_type* __restrict__) LCALS_ALIGN_DATA(dptr) )[i];
#else
return( (const Real_type* __restrict__) dptr)[i];
#endif
}
#elif defined(LCALS_COMPILER_XLC12)
const Real_type& operator [] (Index_type i) const
{
LCALS_ALIGN_DATA(dptr);
return( (const Real_type* __restrict__) dptr)[i];
}
#elif defined(LCALS_COMPILER_CLANG)
const Real_type& operator [] (Index_type i) const
{
return( (const_TDRAReal_ptr) dptr)[i];
}
#else
#error LCALS compiler macro is undefined!
#endif
///
/// + operator for pointer arithmetic.
///
const Real_type* operator+ (Index_type i) const { return dptr+i; }
private:
const Real_type* dptr;
};
/*!
******************************************************************************
*
* \brief Class representing a restricted aligned Real_type (non-const) pointer.
*
******************************************************************************
*/
class RestrictAlignedRealPtr
{
public:
///
/// Ctors and assignment op.
///
RestrictAlignedRealPtr() : dptr(0) { ; }
RestrictAlignedRealPtr(Real_type* d) : dptr(d) { ; }
RestrictAlignedRealPtr& operator=(Real_type* d) { RestrictAlignedRealPtr copy(d);
std::swap(dptr, copy.dptr);
return *this; }
///
/// NOTE: Using compiler-generated copy ctor, dtor, and copy assignment op.
///
///
/// Implicit conversion operator to (non-const) bare pointer.
///
operator Real_type*() { return dptr; }
///
/// Implicit conversion operator to const bare pointer.
///
operator const Real_type*() const { return dptr; }
///
/// "Explicit conversion operator" to (non-const) bare pointer,
/// consistent with boost shared ptr.
///
Real_type* get() { return dptr; }
///
/// "Explicit conversion operator" to const bare pointer,
/// consistent with boost shared ptr.
///
const Real_type* get() const { return dptr; }
///
/// Operator that enables implicit conversion from RestrictAlignedRealPtr to
/// RestrictAlignedRealConstPtr.
///
operator ConstRestrictAlignedRealPtr ()
{ return ConstRestrictAlignedRealPtr(dptr); }
///
/// Compiler-specific bracket operators.
///
#if defined(LCALS_COMPILER_ICC)
///
Real_type& operator [] (Index_type i)
{
#if __ICC < 1300 // use alignment intrinsic
LCALS_ALIGN_DATA(dptr);
return( (Real_type* __restrict__) dptr)[i];
#else // use alignment attribute
return( (TDRAReal_ptr) dptr)[i];
#endif
}
///
const Real_type& operator [] (Index_type i) const
{
#if __ICC < 1300 // use alignment intrinsic
LCALS_ALIGN_DATA(dptr);
return( (Real_type* __restrict__) dptr)[i];
#else // use alignment attribute
return( (TDRAReal_ptr) dptr)[i];
#endif
}
#elif defined(LCALS_COMPILER_GNU)
///
Real_type& operator [] (Index_type i)
{
#if 1 // NOTE: alignment instrinsic not available for older GNU compilers
return( (Real_type* __restrict__) LCALS_ALIGN_DATA(dptr) )[i];
#else
return( (Real_type* __restrict__) dptr)[i];
#endif
}
///
const Real_type& operator [] (Index_type i) const
{
#if 1 // NOTE: alignment instrinsic not available for older GNU compilers
return( (Real_type* __restrict__) LCALS_ALIGN_DATA(dptr) )[i];
#else
return( (Real_type* __restrict__) dptr)[i];
#endif
}
#elif defined(LCALS_COMPILER_XLC12)
///
Real_type& operator [] (Index_type i)
{
LCALS_ALIGN_DATA(dptr);
return( (Real_type* __restrict__) dptr)[i];
}
///
const Real_type& operator [] (Index_type i) const
{
LCALS_ALIGN_DATA(dptr);
return( (Real_type* __restrict__) dptr)[i];
}
#elif defined(LCALS_COMPILER_CLANG)
///
Real_type& operator [] (Index_type i)
{
return( (TDRAReal_ptr) dptr)[i];
}
///
const Real_type& operator [] (Index_type i) const
{
return( (TDRAReal_ptr) dptr)[i];
}
#else
#error LCALS compiler macro is undefined!
#endif
///
/// + operator for (non-const) pointer arithmetic.
///
Real_type* operator+ (Index_type i) { return dptr+i; }
///
/// + operator for const pointer arithmetic.
///
const Real_type* operator+ (Index_type i) const { return dptr+i; }
private:
Real_type* dptr;
};
/*!
******************************************************************************
*
* \brief Class representing a restricted Complex_type const pointer.
*
******************************************************************************
*/
class ConstRestrictComplexPtr
{
public:
///
/// Ctors and assignment op.
///
ConstRestrictComplexPtr() : dptr(0) { ; }
ConstRestrictComplexPtr(const Complex_type* d) : dptr(d) { ; }
ConstRestrictComplexPtr& operator=(const Complex_type* d) {
ConstRestrictComplexPtr copy(d);
std::swap(dptr, copy.dptr);
return *this;
}
///
/// NOTE: Using compiler-generated copy ctor, dtor, and copy assignment op.
///
///
/// Implicit conversion operator to bare const pointer.
///
operator const Complex_type*() const { return dptr; }
///
/// "Explicit conversion operator" to bare const pointer,
/// consistent with boost shared ptr.
///
const Complex_type* get() const { return dptr; }
///
/// Bracket operator.
///
const Complex_type& operator [] (Index_type i) const
{
return( (const Complex_type* __restrict__) dptr)[i];
}
///
/// + operator for pointer arithmetic.
///
const Complex_type* operator+ (Index_type i) const { return dptr+i; }
private:
const Complex_type* dptr;
};
/*!
******************************************************************************
*
* \brief Class representing a restricted Complex_type (non-const) pointer.
*
******************************************************************************
*/
class RestrictComplexPtr
{
public:
///
/// Ctors and assignment op.
///
RestrictComplexPtr() : dptr(0) { ; }
RestrictComplexPtr(Complex_type* d) : dptr(d) { ; }
RestrictComplexPtr& operator=(Complex_type* d) { RestrictComplexPtr copy(d);
std::swap(dptr, copy.dptr);
return *this; }
///
/// NOTE: Using compiler-generated copy ctor, dtor, and copy assignment op.
///
///
/// Implicit conversion operator to (non-const) bare pointer.
///
operator Complex_type*() { return dptr; }
///
/// Implicit conversion operator to const bare pointer.
///
operator const Complex_type*() const { return dptr; }
///
/// "Explicit conversion operator" to (non-const) bare pointer,
/// consistent with boost shared ptr.
///
Complex_type* get() { return dptr; }
///
/// "Explicit conversion operator" to const bare pointer,
/// consistent with boost shared ptr.
///
const Complex_type* get() const { return dptr; }
///
/// Operator that enables implicit conversion from RestrictComplexPtr to
/// RestrictComplexConstPtr.
///
operator ConstRestrictComplexPtr ()
{ return ConstRestrictComplexPtr(dptr); }
///
/// (Non-const) bracket operator.
///
Complex_type& operator [] (Index_type i)
{
return( (Complex_type* __restrict__) dptr)[i];
}
///
/// Const bracket operator.
///
const Complex_type& operator [] (Index_type i) const
{
return( (Complex_type* __restrict__) dptr)[i];
}
///
/// + operator for (non-const) pointer arithmetic.
///
Complex_type* operator+ (Index_type i) { return dptr+i; }
///
/// + operator for const pointer arithmetic.
///
const Complex_type* operator+ (Index_type i) const { return dptr+i; }
private:
Complex_type* dptr;
};
#endif // defined(LCALS_USE_PTR_CLASS)
/*
******************************************************************************
*
* Finally, we define data pointer types based on definitions above and
* -D value given at compile time.
*
******************************************************************************
*/
#if defined(LCALS_USE_BARE_PTR)
typedef Real_type* Real_ptr;
typedef const Real_type* const_Real_ptr;
typedef Complex_type* Complex_ptr;
typedef const Complex_type* const_Complex_ptr;
typedef Real_type* UnalignedReal_ptr;
typedef const Real_type* const_UnalignedReal_ptr;
#elif defined(LCALS_USE_RESTRICT_PTR)
typedef Real_type* __restrict__ Real_ptr;
typedef const Real_type* __restrict__ const_Real_ptr;
typedef Complex_type* __restrict__ Complex_ptr;
typedef const Complex_type* __restrict__ const_Complex_ptr;
typedef Real_type* __restrict__ UnalignedReal_ptr;
typedef const Real_type* __restrict__ const_UnalignedReal_ptr;
#elif defined(LCALS_USE_RESTRICT_ALIGNED_PTR)
typedef TDRAReal_ptr Real_ptr;
typedef const_TDRAReal_ptr const_Real_ptr;
typedef Complex_type* __restrict__ Complex_ptr;
typedef const Complex_type* __restrict__ const_Complex_ptr;
typedef Real_type* __restrict__ UnalignedReal_ptr;
typedef const Real_type* __restrict__ const_UnalignedReal_ptr;
#elif defined(LCALS_USE_PTR_CLASS)
typedef RestrictAlignedRealPtr Real_ptr;
typedef ConstRestrictAlignedRealPtr const_Real_ptr;
typedef RestrictComplexPtr Complex_ptr;
typedef ConstRestrictComplexPtr const_Complex_ptr;
typedef RestrictRealPtr UnalignedReal_ptr;
typedef ConstRestrictRealPtr const_UnalignedReal_ptr;
#else
#error LCALS pointer type is undefined!
#endif
//
// By default, all loop variants defined as supported in the
// compiler-specific sections above are turned on here (for
// both compilation and execution).
//
// Loop variants can be turned off via the #define/#undef macros below.
// It's a bit cheesy, but it's simple and it works!
//
// Execution of individual loop variants can also be controlled
// by modifying the strings that get added to the run_loop_variants
// vector in main.cxx
//
//
// Execution policies applicable to "forall" loop variants.
// Traversal method templates are defined in LCALSTraversalMethods.hxx
// header files.
//
// Tag struct types define available forall method execution policies
struct seq_exec {};
struct simd_exec {};
struct omp_parallel_for_exec {};
struct omp_for_nowait_exec {};
//
// Execution policy used in (non-OpenMP) "forall" loop variants.
// To use another policy in all such loops, change this typedef.
//
typedef simd_exec exec_policy;
#endif // closing endif for header file include guard