Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enforce element types of DASH containers to be trivially copyable #293

Merged
merged 8 commits into from
Feb 22, 2017
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ Features:
- Better textual output of unit tests
- Added support for HDF5 groups
- Support patterns with underfilled blocks in dash::io::hdf5
- Allow trivially copyable data types in containers

Bugfixes:

Expand All @@ -39,6 +40,10 @@ Bugfixes:
- Support for HDF5.
- Generate cmake package for DASH and DART
- Added code coverage tests
- Enforce minimum C++ compiler versions:
- GCC: 5.1.0
- Clang: 3.8.0
- Intel: 15.0.0

- New compiler flags:

Expand Down
15 changes: 15 additions & 0 deletions CMakeExt/CompilerFlags.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,10 @@ if ("${CMAKE_CXX_COMPILER_ID}" MATCHES ".*Clang")
CACHE STRING "C++ compiler (clang++) debug symbols flag")
set (CXX_OMP_FLAG ${OpenMP_CXX_FLAGS})
set (CC_OMP_FLAG ${OpenMP_CC_FLAGS})

if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS "3.8.0")
message(FATAL_ERROR "Insufficient Clang version detected (3.8.0) or above required")
endif()
elseif ("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU")
# using GCC
set (CXX_STD_FLAG "--std=c++11"
Expand All @@ -151,6 +155,11 @@ elseif ("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU")
if(ENABLE_LT_OPTIMIZATION)
set (CXX_LTO_FLAG "-flto -fwhole-program -fno-use-linker-plugin")
endif()

if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS "5.1.0")
message(FATAL_ERROR "Insufficient GCC version detected (5.1.0 or above required)")
endif()

elseif ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Intel")
# using Intel C++
set (CXX_STD_FLAG "-std=c++11"
Expand All @@ -163,6 +172,12 @@ elseif ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Intel")
if(ENABLE_CC_REPORTS)
set (CC_REPORT_FLAG "-qopt-report=4 -qopt-report-phase ipo")
endif()


if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS "15.0.0")
message(FATAL_ERROR "Insufficient Intel compiler version detected (15.0.0 or above required)")
endif()

elseif ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Cray")
# Cray compiler not supported for C++
message(FATAL_ERROR,
Expand Down
11 changes: 11 additions & 0 deletions dash/include/dash/Array.h
Original file line number Diff line number Diff line change
Expand Up @@ -635,6 +635,17 @@ template<
>
class Array
{
/**
* The Cray compiler (as of CCE8.5.6) does not support
* std::is_trivially_copyable.
*
* TODO: Remove the guard once this has been fixed by Cray.
*/
#ifndef __CRAYC
static_assert(std::is_trivially_copyable<ElementType>::value,
"Element type must be trivially copyable");
#endif

private:
typedef Array<ElementType, IndexType, PatternType> self_t;

Expand Down
33 changes: 7 additions & 26 deletions dash/include/dash/GlobPtr.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,48 +86,29 @@ class GlobPtr
/**
* Default constructor, underlying global address is unspecified.
*/
explicit GlobPtr() = default;
constexpr explicit GlobPtr() = default;

/**
* Constructor, specifies underlying global address.
*/
explicit GlobPtr(dart_gptr_t gptr)
{
DASH_LOG_TRACE_VAR("GlobPtr(dart_gptr_t)", gptr);
_dart_gptr = gptr;
}
constexpr explicit GlobPtr(dart_gptr_t gptr) : _dart_gptr(gptr)
{ }

/**
* Constructor for conversion of std::nullptr_t.
*/
GlobPtr(std::nullptr_t p)
{
DASH_LOG_TRACE("GlobPtr()", "nullptr");
_dart_gptr = DART_GPTR_NULL;
}
constexpr GlobPtr(std::nullptr_t p) : _dart_gptr(DART_GPTR_NULL)
{ }

/**
* Copy constructor.
*/
GlobPtr(const self_t & other)
: _dart_gptr(other._dart_gptr)
{
DASH_LOG_TRACE("GlobPtr()", "GlobPtr<T> other");
}
constexpr GlobPtr(const self_t & other) = default;

/**
* Assignment operator.
*/
self_t & operator=(const self_t & rhs)
{
DASH_LOG_TRACE("GlobPtr.=()", "GlobPtr<T> rhs");
DASH_LOG_TRACE_VAR("GlobPtr.=", rhs);
if (this != &rhs) {
_dart_gptr = rhs._dart_gptr;
}
DASH_LOG_TRACE("GlobPtr.= >");
return *this;
}
self_t & operator=(const self_t & rhs) = default;

/**
* Converts pointer to its underlying global address.
Expand Down
11 changes: 11 additions & 0 deletions dash/include/dash/List.h
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,17 @@ template<
class AllocatorType = dash::allocator::DynamicAllocator<ElementType> >
class List
{
/**
* The Cray compiler (as of CCE8.5.6) does not support
* std::is_trivially_copyable.
*
* TODO: Remove the guard once this has been fixed by Cray.
*/
#ifndef __CRAYC
static_assert(std::is_trivially_copyable<ElementType>::value,
"Element type must be trivially copyable");
#endif

template<typename T_, class A_>
friend class LocalListRef;

Expand Down
13 changes: 8 additions & 5 deletions dash/include/dash/Matrix.h
Original file line number Diff line number Diff line change
Expand Up @@ -135,13 +135,16 @@ template<
class PatternT = TilePattern<NumDimensions, ROW_MAJOR, IndexT> >
class Matrix
{
#if !defined(_CRAYC) && !defined(__INTEL_COMPILER)
// Cray and Intel compilers still does not support this feature
/**
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Intel compilers (tested 16.0 and 17.0) don't allow std::is_trivially_copyable either. Why did you remove this check?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because they do. I just tested with Intel 17.0 and I am sure I also verified 16 back when we discussed #241. Keep in mind that the Intel compiler relies on the GNU-provided STL so you might have to load a newer GCC module (at least I have to do that on our Linux cluster).

Copy link
Member

@fuchsto fuchsto Feb 22, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, that seems alright.
I actually did test exactly that, but it's apparently specific to our dev server. When reloading gcc after loading the icc module, there is some hickup and the newer version of gcc is not used.

* The Cray compiler (as of CCE8.5.6) does not support
* std::is_trivially_copyable.
*
* TODO: Remove the guard once this has been fixed by Cray.
*/
#ifndef __CRAYC
static_assert(std::is_trivially_copyable<ElementT>::value,
"Element type must be trivial copyable");
"Element type must be trivially copyable");
#endif
static_assert(std::is_standard_layout<ElementT>::value,
"Element type must have standard layout");
static_assert(std::is_same<IndexT, typename PatternT::index_type>::value,
"Index type IndexT must be the same for Matrix and specified pattern");

Expand Down
210 changes: 210 additions & 0 deletions dash/include/dash/Pair.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,210 @@
#ifndef DASH_DASH_INCLUDE_DASH_PAIR_H_
#define DASH_DASH_INCLUDE_DASH_PAIR_H_

#include <type_traits>

namespace dash {

/**
* A trivially-copyable implementation of std::pair to be used
* as element type of DASH containers.
*
* The implementation was mainly taken and adapted from std_pair.h.
*
* \todo Implementation of tuples are missing at the moment.
*/
template<class T1, class T2>
struct Pair
{
typedef T1 first_type; /// @c first_type is the first bound type
typedef T2 second_type; /// @c second_type is the second bound type

T1 first; /// @c first is a copy of the first object
T2 second; /// @c second is a copy of the second object

/**
* The default constructor.
*/
constexpr Pair()
: first(), second()
{ }

/**
* Two objects may be passed to a Pair constructor to be copied.
*/
constexpr Pair(const T1& __a, const T2& __b)
: first(__a), second(__b)
{ }

/**
* A Pair might be constructed from another pair iff first and second
* are convertible.
*/
template<class U1, class U2, class = typename
std::enable_if<
std::is_convertible<const U1&, T1>::value &&
std::is_convertible<const U2&, T2>::value>::value>
constexpr Pair(const Pair<U1, U2>& p)
: first(p.first), second(p.second)
{ }

constexpr Pair(const Pair&) = default;
constexpr Pair(Pair&&) = default;

template<class U1, class = typename
std::enable_if<std::is_convertible<U1, T1>::value>::type>
constexpr Pair(U1&& x, const T2& y)
: first(std::forward<U1>(x)), second(y)
{ }

template<class U2, class = typename
std::enable_if<std::is_convertible<U2, T2>::value>::type>
constexpr Pair(const T1& x, U2&& y)
: first(x), second(std::forward<U2>(y))
{ }

template<class U1, class U2, class = typename
std::enable_if<std::is_convertible<U1, T1>::value &&
std::is_convertible<U2, T2>::value>::type>
constexpr Pair(U1&& x, U2&& y)
: first(std::forward<U1>(x)), second(std::forward<U2>(y))
{ }

template<class U1, class U2, class = typename
std::enable_if<std::is_convertible<U1, T1>::value &&
std::is_convertible<U2, T2>::value>::type>
constexpr Pair(Pair<U1, U2>&& p)
: first(std::forward<U1>(p.first)),
second(std::forward<U2>(p.second))
{ }

Pair&
operator=(const Pair& p) = default;

Pair&
operator=(Pair&& p)
noexcept(
std::is_nothrow_move_assignable<T1>::value &&
std::is_nothrow_move_assignable<T2>::value) = default;

template<class U1, class U2>
Pair&
operator=(const Pair<U1, U2>& p)
{
first = p.first;
second = p.second;
return *this;
}

template<class U1, class U2>
Pair&
operator=(Pair<U1, U2>&& p)
{
first = std::forward<U1>(p.first);
second = std::forward<U2>(p.second);
return *this;
}

void
swap(Pair& p)
noexcept(noexcept(swap(first, p.first))
&& noexcept(swap(second, p.second)))
{
std::swap(first, p.first);
std::swap(second, p.second);
}
};

/**
* Two pairs of the same type are equal iff their members are equal.
*/
template<class T1, class T2>
inline constexpr bool
operator==(const Pair<T1, T2>& x, const Pair<T1, T2>& y)
{
return x.first == y.first && x.second == y.second;
}

/**
* A pair is smaller than another pair if the first member is smaller
* or the first is equal and the second is smaller.
* See <http://gcc.gnu.org/onlinedocs/libstdc++/manual/utilities.html>
*/
template<class T1, class T2>
inline constexpr bool
operator<(const Pair<T1, T2>& x, const Pair<T1, T2>& y)
{
return x.first < y.first
|| (!(y.first < x.first) && !(x.second >= y.second));
}

/**
* Inequality comparison operator implemented in terms of
* equality operator.
*/
template<class T1, class T2>
inline constexpr bool
operator!=(const Pair<T1, T2>& x, const Pair<T1, T2>& y)
{
return !(x == y);
}

/**
* Greater-than operator implemented in terms of less-than operator.
*/
template<class T1, class T2>
inline constexpr bool
operator>(const Pair<T1, T2>& x, const Pair<T1, T2>& y)
{
return y < x;
}

/**
* Less-than-or-equal operator implemented in terms of less-than operator.
*/
template<class T1, class T2>
inline constexpr bool
operator<=(const Pair<T1, T2>& x, const Pair<T1, T2>& y)
{
return !(y < x);
}

/**
* Greater-than-or-equal operator implemented in terms of less-than operator.
*/
template<class T1, class T2>
inline constexpr bool
operator>=(const Pair<T1, T2>& x, const Pair<T1, T2>& y)
{
return !(x < y);
}

/**
* Wrapper for Pair::swap.
*/
template<class T1, class T2>
inline void
swap(Pair<T1, T2>& x, Pair<T1, T2>& y)
noexcept(noexcept(x.swap(y)))
{
x.swap(y);
}

/**
* Convennience wrapper to create a Pair object.
*/
template<class T1, class T2>
constexpr Pair<typename std::__decay_and_strip<T1>::__type,
typename std::__decay_and_strip<T2>::__type>
make_pair(T1&& x, T2&& y)
{
typedef typename std::__decay_and_strip<T1>::__type ds_type1;
typedef typename std::__decay_and_strip<T2>::__type ds_type2;
typedef Pair<ds_type1, ds_type2> pair_type;
return pair_type(std::forward<T1>(x), std::forward<T2>(y));
}

} // namespace dash


#endif /* DASH_DASH_INCLUDE_DASH_PAIR_H_ */
13 changes: 13 additions & 0 deletions dash/include/dash/map/UnorderedMap.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,19 @@ template<
std::pair<const Key, Mapped> > >
class UnorderedMap
{
/**
* The Cray compiler (as of CCE8.5.6) does not support
* std::is_trivially_copyable.
*
* TODO: Remove the guard once this has been fixed by Cray.
*/
#ifndef __CRAYC
static_assert(std::is_trivially_copyable<Key>::value,
"Element type must be trivially copyable");
static_assert(std::is_trivially_copyable<Mapped>::value,
"Element type must be trivially copyable");
#endif

template<typename K_, typename M_, typename H_, typename P_, typename A_>
friend class UnorderedMapLocalRef;

Expand Down
Loading