Files
lammps/lib/kokkos/core/unit_test/TestReducers.hpp
2018-11-12 15:16:26 -07:00

921 lines
29 KiB
C++

/*
//@HEADER
// ************************************************************************
//
// Kokkos v. 2.0
// Copyright (2014) Sandia Corporation
//
// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
// the U.S. Government retains certain rights in this software.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// 1. Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// 3. Neither the name of the Corporation nor the names of the
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Questions? Contact Christian R. Trott (crtrott@sandia.gov)
//
// ************************************************************************
//@HEADER
*/
#include <stdexcept>
#include <sstream>
#include <iostream>
#include <limits>
#include <Kokkos_Core.hpp>
//--------------------------------------------------------------------------
namespace Test {
struct ReducerTag {};
template< class Scalar, class ExecSpace = Kokkos::DefaultExecutionSpace >
struct TestReducers {
struct SumFunctor {
Kokkos::View< const Scalar*, ExecSpace > values;
KOKKOS_INLINE_FUNCTION
void operator()( const int & i, Scalar & value ) const {
value += values( i );
}
};
struct ProdFunctor {
Kokkos::View< const Scalar*, ExecSpace > values;
KOKKOS_INLINE_FUNCTION
void operator()( const int & i, Scalar & value ) const {
value *= values( i );
}
};
struct MinFunctor {
Kokkos::View< const Scalar*, ExecSpace > values;
KOKKOS_INLINE_FUNCTION
void operator()( const int & i, Scalar & value ) const {
if ( values( i ) < value ) value = values( i );
}
};
struct MaxFunctor {
Kokkos::View< const Scalar*, ExecSpace > values;
KOKKOS_INLINE_FUNCTION
void operator()( const int & i, Scalar & value ) const {
if ( values( i ) > value ) value = values( i );
}
};
struct MinLocFunctor {
Kokkos::View< const Scalar*, ExecSpace > values;
KOKKOS_INLINE_FUNCTION
void operator()( const int & i, typename Kokkos::MinLoc< Scalar, int >::value_type & value ) const {
if ( values( i ) < value.val ) {
value.val = values( i );
value.loc = i;
}
}
};
struct MaxLocFunctor {
Kokkos::View< const Scalar*, ExecSpace > values;
KOKKOS_INLINE_FUNCTION
void operator()( const int & i, typename Kokkos::MaxLoc< Scalar, int >::value_type & value ) const {
if ( values( i ) > value.val ) {
value.val = values( i );
value.loc = i;
}
}
};
struct MinMaxLocFunctor {
Kokkos::View< const Scalar*, ExecSpace > values;
KOKKOS_INLINE_FUNCTION
void operator()( const int & i, typename Kokkos::MinMaxLoc< Scalar, int >::value_type & value ) const {
if ( values( i ) > value.max_val ) {
value.max_val = values( i );
value.max_loc = i;
}
if ( values( i ) < value.min_val ) {
value.min_val = values( i );
value.min_loc = i;
}
}
};
struct BAndFunctor {
Kokkos::View< const Scalar*, ExecSpace > values;
KOKKOS_INLINE_FUNCTION
void operator()( const int & i, Scalar & value ) const {
value = value & values( i );
}
};
struct BOrFunctor {
Kokkos::View< const Scalar*, ExecSpace > values;
KOKKOS_INLINE_FUNCTION
void operator()( const int & i, Scalar & value ) const {
value = value | values( i );
}
};
struct LAndFunctor {
Kokkos::View< const Scalar*, ExecSpace > values;
KOKKOS_INLINE_FUNCTION
void operator()( const int & i, Scalar & value ) const {
value = value && values( i );
}
};
struct LOrFunctor {
Kokkos::View< const Scalar*, ExecSpace > values;
KOKKOS_INLINE_FUNCTION
void operator()( const int & i, Scalar & value ) const {
value = value || values( i );
}
};
struct SumFunctorTag {
Kokkos::View< const Scalar*, ExecSpace > values;
KOKKOS_INLINE_FUNCTION
void operator()( const ReducerTag, const int & i, Scalar & value ) const {
value += values( i );
}
};
struct ProdFunctorTag {
Kokkos::View< const Scalar*, ExecSpace > values;
KOKKOS_INLINE_FUNCTION
void operator()( const ReducerTag, const int & i, Scalar & value ) const {
value *= values( i );
}
};
struct MinFunctorTag {
Kokkos::View< const Scalar*, ExecSpace > values;
KOKKOS_INLINE_FUNCTION
void operator()( const ReducerTag, const int & i, Scalar & value ) const {
if ( values( i ) < value ) value = values( i );
}
};
struct MaxFunctorTag {
Kokkos::View< const Scalar*, ExecSpace > values;
KOKKOS_INLINE_FUNCTION
void operator()( const ReducerTag, const int & i, Scalar & value ) const {
if ( values( i ) > value ) value = values( i );
}
};
struct MinLocFunctorTag {
Kokkos::View< const Scalar*, ExecSpace > values;
KOKKOS_INLINE_FUNCTION
void operator()( const ReducerTag, const int & i, typename Kokkos::MinLoc< Scalar, int >::value_type & value ) const {
if ( values( i ) < value.val ) {
value.val = values( i );
value.loc = i;
}
}
};
struct MaxLocFunctorTag {
Kokkos::View< const Scalar*, ExecSpace > values;
KOKKOS_INLINE_FUNCTION
void operator()( const ReducerTag, const int & i, typename Kokkos::MaxLoc< Scalar, int >::value_type & value ) const {
if ( values( i ) > value.val ) {
value.val = values( i );
value.loc = i;
}
}
};
struct MinMaxLocFunctorTag {
Kokkos::View< const Scalar*, ExecSpace > values;
KOKKOS_INLINE_FUNCTION
void operator()( const ReducerTag, const int & i, typename Kokkos::MinMaxLoc< Scalar, int >::value_type & value ) const {
if ( values( i ) > value.max_val ) {
value.max_val = values( i );
value.max_loc = i;
}
if ( values( i ) < value.min_val ) {
value.min_val = values( i );
value.min_loc = i;
}
}
};
struct BAndFunctorTag {
Kokkos::View< const Scalar*, ExecSpace > values;
KOKKOS_INLINE_FUNCTION
void operator()( const ReducerTag, const int & i, Scalar & value ) const {
value = value & values( i );
}
};
struct BOrFunctorTag {
Kokkos::View< const Scalar*, ExecSpace > values;
KOKKOS_INLINE_FUNCTION
void operator()( const ReducerTag, const int & i, Scalar & value ) const {
value = value | values( i );
}
};
struct LAndFunctorTag {
Kokkos::View< const Scalar*, ExecSpace > values;
KOKKOS_INLINE_FUNCTION
void operator()( const ReducerTag, const int & i, Scalar & value ) const {
value = value && values( i );
}
};
struct LOrFunctorTag {
Kokkos::View< const Scalar*, ExecSpace > values;
KOKKOS_INLINE_FUNCTION
void operator()( const ReducerTag, const int & i, Scalar & value ) const {
value = value || values( i );
}
};
static void test_sum( int N ) {
Kokkos::View< Scalar*, ExecSpace > values( "Values", N );
auto h_values = Kokkos::create_mirror_view( values );
Scalar reference_sum = 0;
for ( int i = 0; i < N; i++ ) {
h_values( i ) = (Scalar) ( rand() % 100 );
reference_sum += h_values( i );
}
Kokkos::deep_copy( values, h_values );
SumFunctor f;
f.values = values;
SumFunctorTag f_tag;
f_tag.values = values;
Scalar init = 0;
{
Scalar sum_scalar = init;
Kokkos::Sum< Scalar > reducer_scalar( sum_scalar );
Kokkos::parallel_reduce( Kokkos::RangePolicy< ExecSpace >( 0, N ), f, reducer_scalar );
ASSERT_EQ( sum_scalar, reference_sum );
sum_scalar = init;
Kokkos::parallel_reduce( Kokkos::RangePolicy< ExecSpace , ReducerTag >( 0, N ), f_tag, reducer_scalar );
ASSERT_EQ( sum_scalar, reference_sum );
Scalar sum_scalar_view = reducer_scalar.reference();
ASSERT_EQ( sum_scalar_view, reference_sum );
}
{
Kokkos::View< Scalar, Kokkos::HostSpace> sum_view( "View" );
sum_view() = init;
Kokkos::Sum< Scalar > reducer_view( sum_view );
Kokkos::parallel_reduce( Kokkos::RangePolicy< ExecSpace >( 0, N ), f, reducer_view );
Scalar sum_view_scalar = sum_view();
ASSERT_EQ( sum_view_scalar, reference_sum );
Scalar sum_view_view = reducer_view.reference();
ASSERT_EQ( sum_view_view, reference_sum );
}
}
static void test_prod( int N ) {
Kokkos::View< Scalar*, ExecSpace > values( "Values", N );
auto h_values = Kokkos::create_mirror_view( values );
Scalar reference_prod = 1;
for ( int i = 0; i < N; i++ ) {
h_values( i ) = (Scalar) ( rand() % 4 + 1 );
reference_prod *= h_values( i );
}
Kokkos::deep_copy( values, h_values );
ProdFunctor f;
f.values = values;
ProdFunctorTag f_tag;
f_tag.values = values;
Scalar init = 1;
{
Scalar prod_scalar = init;
Kokkos::Prod< Scalar > reducer_scalar( prod_scalar );
Kokkos::parallel_reduce( Kokkos::RangePolicy< ExecSpace >( 0, N ), f, reducer_scalar );
ASSERT_EQ( prod_scalar, reference_prod );
prod_scalar = init;
Kokkos::parallel_reduce( Kokkos::RangePolicy< ExecSpace , ReducerTag >( 0, N ), f_tag, reducer_scalar );
ASSERT_EQ( prod_scalar, reference_prod );
Scalar prod_scalar_view = reducer_scalar.reference();
ASSERT_EQ( prod_scalar_view, reference_prod );
}
{
Kokkos::View< Scalar, Kokkos::HostSpace > prod_view( "View" );
prod_view() = init;
Kokkos::Prod< Scalar > reducer_view( prod_view );
Kokkos::parallel_reduce( Kokkos::RangePolicy< ExecSpace >( 0, N ), f, reducer_view );
Scalar prod_view_scalar = prod_view();
ASSERT_EQ( prod_view_scalar, reference_prod );
Scalar prod_view_view = reducer_view.reference();
ASSERT_EQ( prod_view_view, reference_prod );
}
}
static void test_min( int N ) {
Kokkos::View< Scalar*, ExecSpace > values( "Values", N );
auto h_values = Kokkos::create_mirror_view( values );
Scalar reference_min = std::numeric_limits< Scalar >::max();
for ( int i = 0; i < N; i++ ) {
h_values( i ) = (Scalar) ( rand() % 100000 );
if ( h_values( i ) < reference_min ) reference_min = h_values( i );
}
Kokkos::deep_copy( values, h_values );
MinFunctor f;
f.values = values;
MinFunctorTag f_tag;
f_tag.values = values;
Scalar init = std::numeric_limits< Scalar >::max();
{
Scalar min_scalar = init;
Kokkos::Min< Scalar > reducer_scalar( min_scalar );
Kokkos::parallel_reduce( Kokkos::RangePolicy< ExecSpace >( 0, N ), f, reducer_scalar );
ASSERT_EQ( min_scalar, reference_min );
min_scalar = init;
Kokkos::parallel_reduce( Kokkos::RangePolicy< ExecSpace , ReducerTag >( 0, N ), f_tag, reducer_scalar );
ASSERT_EQ( min_scalar, reference_min );
Scalar min_scalar_view = reducer_scalar.reference();
ASSERT_EQ( min_scalar_view, reference_min );
}
{
Kokkos::View< Scalar, Kokkos::HostSpace > min_view( "View" );
min_view() = init;
Kokkos::Min< Scalar > reducer_view( min_view );
Kokkos::parallel_reduce( Kokkos::RangePolicy< ExecSpace >( 0, N ), f, reducer_view );
Scalar min_view_scalar = min_view();
ASSERT_EQ( min_view_scalar, reference_min );
Scalar min_view_view = reducer_view.reference();
ASSERT_EQ( min_view_view, reference_min );
}
}
static void test_max( int N ) {
Kokkos::View< Scalar*, ExecSpace > values( "Values", N );
auto h_values = Kokkos::create_mirror_view( values );
Scalar reference_max = std::numeric_limits< Scalar >::min();
for ( int i = 0; i < N; i++ ) {
h_values( i ) = (Scalar) ( rand() % 100000 + 1 );
if ( h_values( i ) > reference_max ) reference_max = h_values( i );
}
Kokkos::deep_copy( values, h_values );
MaxFunctor f;
f.values = values;
MaxFunctorTag f_tag;
f_tag.values = values;
Scalar init = std::numeric_limits< Scalar >::min();
{
Scalar max_scalar = init;
Kokkos::Max< Scalar > reducer_scalar( max_scalar );
Kokkos::parallel_reduce( Kokkos::RangePolicy< ExecSpace >( 0, N ), f, reducer_scalar );
ASSERT_EQ( max_scalar, reference_max );
max_scalar = init;
Kokkos::parallel_reduce( Kokkos::RangePolicy< ExecSpace , ReducerTag >( 0, N ), f_tag, reducer_scalar );
ASSERT_EQ( max_scalar, reference_max );
Scalar max_scalar_view = reducer_scalar.reference();
ASSERT_EQ( max_scalar_view, reference_max );
}
{
Kokkos::View< Scalar, Kokkos::HostSpace > max_view( "View" );
max_view() = init;
Kokkos::Max< Scalar > reducer_view( max_view );
Kokkos::parallel_reduce( Kokkos::RangePolicy< ExecSpace >( 0, N ), f, reducer_view );
Scalar max_view_scalar = max_view();
ASSERT_EQ( max_view_scalar, reference_max );
Scalar max_view_view = reducer_view.reference();
ASSERT_EQ( max_view_view, reference_max );
}
}
static void test_minloc( int N ) {
typedef typename Kokkos::MinLoc< Scalar, int >::value_type value_type;
Kokkos::View< Scalar*, ExecSpace > values( "Values", N );
auto h_values = Kokkos::create_mirror_view( values );
Scalar reference_min = std::numeric_limits< Scalar >::max();
int reference_loc = -1;
for ( int i = 0; i < N; i++ ) {
h_values( i ) = (Scalar) ( rand() % 100000 + 2 );
if ( h_values( i ) < reference_min ) {
reference_min = h_values( i );
reference_loc = i;
}
else if ( h_values( i ) == reference_min ) {
// Make min unique.
h_values( i ) += Scalar(1);
}
}
Kokkos::deep_copy( values, h_values );
MinLocFunctor f;
f.values = values;
MinLocFunctorTag f_tag;
f_tag.values = values;
{
value_type min_scalar;
Kokkos::MinLoc< Scalar, int > reducer_scalar( min_scalar );
Kokkos::parallel_reduce( Kokkos::RangePolicy< ExecSpace >( 0, N ), f, reducer_scalar );
ASSERT_EQ( min_scalar.val, reference_min );
ASSERT_EQ( min_scalar.loc, reference_loc );
min_scalar = value_type();
Kokkos::parallel_reduce( Kokkos::RangePolicy< ExecSpace , ReducerTag >( 0, N ), f_tag, reducer_scalar );
ASSERT_EQ( min_scalar.val, reference_min );
ASSERT_EQ( min_scalar.loc, reference_loc );
value_type min_scalar_view = reducer_scalar.reference();
ASSERT_EQ( min_scalar_view.val, reference_min );
ASSERT_EQ( min_scalar_view.loc, reference_loc );
}
{
Kokkos::View< value_type, Kokkos::HostSpace > min_view( "View" );
Kokkos::MinLoc< Scalar, int > reducer_view( min_view );
Kokkos::parallel_reduce( Kokkos::RangePolicy< ExecSpace >( 0, N ), f, reducer_view );
value_type min_view_scalar = min_view();
ASSERT_EQ( min_view_scalar.val, reference_min );
ASSERT_EQ( min_view_scalar.loc, reference_loc );
value_type min_view_view = reducer_view.reference();
ASSERT_EQ( min_view_view.val, reference_min );
ASSERT_EQ( min_view_view.loc, reference_loc );
}
}
static void test_maxloc( int N ) {
typedef typename Kokkos::MaxLoc< Scalar, int >::value_type value_type;
Kokkos::View< Scalar*, ExecSpace > values( "Values", N );
auto h_values = Kokkos::create_mirror_view( values );
Scalar reference_max = std::numeric_limits< Scalar >::min();
int reference_loc = -1;
for ( int i = 0; i < N; i++ ) {
h_values( i ) = (Scalar) ( rand() % 100000 + 2 );
if ( h_values( i ) > reference_max ) {
reference_max = h_values( i );
reference_loc = i;
}
else if ( h_values( i ) == reference_max ) {
// Make max unique.
h_values( i ) -= Scalar(1);
}
}
Kokkos::deep_copy( values, h_values );
MaxLocFunctor f;
f.values = values;
MaxLocFunctorTag f_tag;
f_tag.values = values;
{
value_type max_scalar;
Kokkos::MaxLoc< Scalar, int > reducer_scalar( max_scalar );
Kokkos::parallel_reduce( Kokkos::RangePolicy< ExecSpace >( 0, N ), f, reducer_scalar );
ASSERT_EQ( max_scalar.val, reference_max );
ASSERT_EQ( max_scalar.loc, reference_loc );
max_scalar = value_type();
Kokkos::parallel_reduce( Kokkos::RangePolicy< ExecSpace , ReducerTag >( 0, N ), f_tag, reducer_scalar );
ASSERT_EQ( max_scalar.val, reference_max );
ASSERT_EQ( max_scalar.loc, reference_loc );
value_type max_scalar_view = reducer_scalar.reference();
ASSERT_EQ( max_scalar_view.val, reference_max );
ASSERT_EQ( max_scalar_view.loc, reference_loc );
}
{
Kokkos::View< value_type, Kokkos::HostSpace > max_view( "View" );
Kokkos::MaxLoc< Scalar, int > reducer_view( max_view );
Kokkos::parallel_reduce( Kokkos::RangePolicy< ExecSpace >( 0, N ), f, reducer_view );
value_type max_view_scalar = max_view();
ASSERT_EQ( max_view_scalar.val, reference_max );
ASSERT_EQ( max_view_scalar.loc, reference_loc );
value_type max_view_view = reducer_view.reference();
ASSERT_EQ( max_view_view.val, reference_max );
ASSERT_EQ( max_view_view.loc, reference_loc );
}
}
static void test_minmaxloc( int N ) {
typedef typename Kokkos::MinMaxLoc< Scalar, int >::value_type value_type;
Kokkos::View< Scalar*, ExecSpace > values( "Values", N );
auto h_values = Kokkos::create_mirror_view( values );
Scalar reference_max = std::numeric_limits< Scalar >::min();
Scalar reference_min = std::numeric_limits< Scalar >::max();
int reference_minloc = -1;
int reference_maxloc = -1;
for ( int i = 0; i < N; i++ ) {
h_values( i ) = (Scalar) ( rand() % 100000 + 2);
}
for ( int i = 0; i < N; i++ ) {
if ( h_values( i ) > reference_max ) {
reference_max = h_values( i );
reference_maxloc = i;
}
else if ( h_values( i ) == reference_max ) {
// Make max unique.
h_values( i ) -= Scalar(1);
}
}
for ( int i = 0; i < N; i++ ) {
if ( h_values( i ) < reference_min ) {
reference_min = h_values( i );
reference_minloc = i;
}
else if ( h_values( i ) == reference_min ) {
// Make min unique.
h_values( i ) += Scalar(1);
}
}
Kokkos::deep_copy( values, h_values );
MinMaxLocFunctor f;
f.values = values;
MinMaxLocFunctorTag f_tag;
f_tag.values = values;
{
value_type minmax_scalar;
Kokkos::MinMaxLoc< Scalar, int > reducer_scalar( minmax_scalar );
Kokkos::parallel_reduce( Kokkos::RangePolicy< ExecSpace >( 0, N ), f, reducer_scalar );
ASSERT_EQ( minmax_scalar.min_val, reference_min );
for ( int i = 0; i < N; i++ ) {
if ( ( i == minmax_scalar.min_loc ) && ( h_values( i ) == reference_min ) ) {
reference_minloc = i;
}
}
ASSERT_EQ( minmax_scalar.min_loc, reference_minloc );
ASSERT_EQ( minmax_scalar.max_val, reference_max );
for ( int i = 0; i < N; i++ ) {
if ( ( i == minmax_scalar.max_loc ) && ( h_values( i ) == reference_max ) ) {
reference_maxloc = i;
}
}
ASSERT_EQ( minmax_scalar.max_loc, reference_maxloc );
minmax_scalar = value_type();
Kokkos::parallel_reduce( Kokkos::RangePolicy< ExecSpace , ReducerTag >( 0, N ), f_tag, reducer_scalar );
ASSERT_EQ( minmax_scalar.min_val, reference_min );
for ( int i = 0; i < N; i++ ) {
if ( ( i == minmax_scalar.min_loc ) && ( h_values( i ) == reference_min ) ) {
reference_minloc = i;
}
}
ASSERT_EQ( minmax_scalar.min_loc, reference_minloc );
ASSERT_EQ( minmax_scalar.max_val, reference_max );
for ( int i = 0; i < N; i++ ) {
if ( ( i == minmax_scalar.max_loc ) && ( h_values( i ) == reference_max ) ) {
reference_maxloc = i;
}
}
ASSERT_EQ( minmax_scalar.max_loc, reference_maxloc );
value_type minmax_scalar_view = reducer_scalar.reference();
ASSERT_EQ( minmax_scalar_view.min_val, reference_min );
ASSERT_EQ( minmax_scalar_view.min_loc, reference_minloc );
ASSERT_EQ( minmax_scalar_view.max_val, reference_max );
ASSERT_EQ( minmax_scalar_view.max_loc, reference_maxloc );
}
{
Kokkos::View< value_type, Kokkos::HostSpace > minmax_view( "View" );
Kokkos::MinMaxLoc< Scalar, int > reducer_view( minmax_view );
Kokkos::parallel_reduce( Kokkos::RangePolicy< ExecSpace >( 0, N ), f, reducer_view );
value_type minmax_view_scalar = minmax_view();
ASSERT_EQ( minmax_view_scalar.min_val, reference_min );
ASSERT_EQ( minmax_view_scalar.min_loc, reference_minloc );
ASSERT_EQ( minmax_view_scalar.max_val, reference_max );
ASSERT_EQ( minmax_view_scalar.max_loc, reference_maxloc );
value_type minmax_view_view = reducer_view.reference();
ASSERT_EQ( minmax_view_view.min_val, reference_min );
ASSERT_EQ( minmax_view_view.min_loc, reference_minloc );
ASSERT_EQ( minmax_view_view.max_val, reference_max );
ASSERT_EQ( minmax_view_view.max_loc, reference_maxloc );
}
}
static void test_BAnd( int N ) {
Kokkos::View< Scalar*, ExecSpace > values( "Values", N );
auto h_values = Kokkos::create_mirror_view( values );
Scalar reference_band = Scalar() | ( ~Scalar() );
for ( int i = 0; i < N; i++ ) {
h_values( i ) = (Scalar) ( rand() % 100000 + 1 );
reference_band = reference_band & h_values( i );
}
Kokkos::deep_copy( values, h_values );
BAndFunctor f;
f.values = values;
BAndFunctorTag f_tag;
f_tag.values = values;
Scalar init = Scalar() | ( ~Scalar() );
{
Scalar band_scalar = init;
Kokkos::BAnd< Scalar > reducer_scalar( band_scalar );
Kokkos::parallel_reduce( Kokkos::RangePolicy< ExecSpace >( 0, N ), f, reducer_scalar );
ASSERT_EQ( band_scalar, reference_band );
band_scalar = init;
Kokkos::parallel_reduce( Kokkos::RangePolicy< ExecSpace , ReducerTag >( 0, N ), f_tag, reducer_scalar );
ASSERT_EQ( band_scalar, reference_band );
Scalar band_scalar_view = reducer_scalar.reference();
ASSERT_EQ( band_scalar_view, reference_band );
}
{
Kokkos::View< Scalar, Kokkos::HostSpace > band_view( "View" );
band_view() = init;
Kokkos::BAnd< Scalar > reducer_view( band_view );
Kokkos::parallel_reduce( Kokkos::RangePolicy< ExecSpace >( 0, N ), f, reducer_view );
Scalar band_view_scalar = band_view();
ASSERT_EQ( band_view_scalar, reference_band );
Scalar band_view_view = reducer_view.reference();
ASSERT_EQ( band_view_view, reference_band );
}
}
static void test_BOr( int N ) {
Kokkos::View< Scalar*, ExecSpace > values( "Values", N );
auto h_values = Kokkos::create_mirror_view( values );
Scalar reference_bor = Scalar() & ( ~Scalar() );
for ( int i = 0; i < N; i++ ) {
h_values( i ) = (Scalar) ( ( rand() % 100000 + 1 ) * 2 );
reference_bor = reference_bor | h_values( i );
}
Kokkos::deep_copy( values, h_values );
BOrFunctor f;
f.values = values;
BOrFunctorTag f_tag;
f_tag.values = values;
Scalar init = Scalar() & ( ~Scalar() );
{
Scalar bor_scalar = init;
Kokkos::BOr< Scalar > reducer_scalar( bor_scalar );
Kokkos::parallel_reduce( Kokkos::RangePolicy< ExecSpace >( 0, N ), f, reducer_scalar );
ASSERT_EQ( bor_scalar, reference_bor );
bor_scalar = init;
Kokkos::parallel_reduce( Kokkos::RangePolicy< ExecSpace , ReducerTag >( 0, N ), f_tag, reducer_scalar );
ASSERT_EQ( bor_scalar, reference_bor );
Scalar bor_scalar_view = reducer_scalar.reference();
ASSERT_EQ( bor_scalar_view, reference_bor );
}
{
Kokkos::View< Scalar, Kokkos::HostSpace > bor_view( "View" );
bor_view() = init;
Kokkos::BOr< Scalar > reducer_view( bor_view );
Kokkos::parallel_reduce( Kokkos::RangePolicy< ExecSpace >( 0, N ), f, reducer_view );
Scalar bor_view_scalar = bor_view();
ASSERT_EQ( bor_view_scalar, reference_bor );
Scalar bor_view_view = reducer_view.reference();
ASSERT_EQ( bor_view_view, reference_bor );
}
}
static void test_LAnd( int N ) {
Kokkos::View< Scalar*, ExecSpace > values( "Values", N );
auto h_values = Kokkos::create_mirror_view( values );
Scalar reference_land = 1;
for ( int i = 0; i < N; i++ ) {
h_values( i ) = (Scalar) ( rand() % 2 );
reference_land = reference_land && h_values( i );
}
Kokkos::deep_copy( values, h_values );
LAndFunctor f;
f.values = values;
LAndFunctorTag f_tag;
f_tag.values = values;
Scalar init = 1;
{
Scalar land_scalar = init;
Kokkos::LAnd< Scalar > reducer_scalar( land_scalar );
Kokkos::parallel_reduce( Kokkos::RangePolicy< ExecSpace >( 0, N ), f, reducer_scalar );
ASSERT_EQ( land_scalar, reference_land );
land_scalar = init;
Kokkos::parallel_reduce( Kokkos::RangePolicy< ExecSpace , ReducerTag >( 0, N ), f_tag, reducer_scalar );
ASSERT_EQ( land_scalar, reference_land );
Scalar land_scalar_view = reducer_scalar.reference();
ASSERT_EQ( land_scalar_view, reference_land );
}
{
Kokkos::View< Scalar, Kokkos::HostSpace > land_view( "View" );
land_view() = init;
Kokkos::LAnd< Scalar > reducer_view( land_view );
Kokkos::parallel_reduce( Kokkos::RangePolicy< ExecSpace >( 0, N ), f, reducer_view );
Scalar land_view_scalar = land_view();
ASSERT_EQ( land_view_scalar, reference_land );
Scalar land_view_view = reducer_view.reference();
ASSERT_EQ( land_view_view, reference_land );
}
}
static void test_LOr( int N ) {
Kokkos::View< Scalar*, ExecSpace > values( "Values", N );
auto h_values = Kokkos::create_mirror_view( values );
Scalar reference_lor = 0;
for ( int i = 0; i < N; i++ ) {
h_values( i ) = (Scalar) ( rand() % 2 );
reference_lor = reference_lor || h_values( i );
}
Kokkos::deep_copy( values, h_values );
LOrFunctor f;
f.values = values;
LOrFunctorTag f_tag;
f_tag.values = values;
Scalar init = 0;
{
Scalar lor_scalar = init;
Kokkos::LOr< Scalar > reducer_scalar( lor_scalar );
Kokkos::parallel_reduce( Kokkos::RangePolicy< ExecSpace >( 0, N ), f, reducer_scalar );
ASSERT_EQ( lor_scalar, reference_lor );
lor_scalar = init;
Kokkos::parallel_reduce( Kokkos::RangePolicy< ExecSpace , ReducerTag >( 0, N ), f_tag, reducer_scalar );
ASSERT_EQ( lor_scalar, reference_lor );
Scalar lor_scalar_view = reducer_scalar.reference();
ASSERT_EQ( lor_scalar_view, reference_lor );
}
{
Kokkos::View< Scalar, Kokkos::HostSpace > lor_view( "View" );
lor_view() = init;
Kokkos::LOr< Scalar > reducer_view( lor_view );
Kokkos::parallel_reduce( Kokkos::RangePolicy< ExecSpace >( 0, N ), f, reducer_view );
Scalar lor_view_scalar = lor_view();
ASSERT_EQ( lor_view_scalar, reference_lor );
Scalar lor_view_view = reducer_view.reference();
ASSERT_EQ( lor_view_view, reference_lor );
}
}
static void execute_float() {
test_sum( 10001 );
test_prod( 35 );
test_min( 10003 );
test_minloc( 10003 );
test_max( 10007 );
test_maxloc( 10007 );
test_minmaxloc( 10007 );
}
static void execute_integer() {
test_sum( 10001 );
test_prod( 35 );
test_min( 10003 );
test_minloc( 10003 );
test_max( 10007 );
test_maxloc( 10007 );
test_minmaxloc( 10007 );
test_BAnd( 35 );
test_BOr( 35 );
test_LAnd( 35 );
test_LOr( 35 );
}
static void execute_basic() {
test_sum( 10001 );
test_prod( 35 );
}
};
} // namespace Test