Skip to content

Commit

Permalink
Added unit test for n-arity math operators
Browse files Browse the repository at this point in the history
Added tests for unary math operators with functors.

Added binaryOps and reworked unaryOps.

Reduced doubled code significantly, by allowing to test operators of n-arity with the same code.

Integrated PR from td11235813

Removed HCC workaround and rebased
NOTE: fast-math needs to be disabled for gpu-backend.
Co-authored-by: Matthias Werner <Matthias.Werner1@tu-dresden.de>
  • Loading branch information
jkrude committed Apr 8, 2020
1 parent 9e1caaf commit b5b6051
Show file tree
Hide file tree
Showing 7 changed files with 968 additions and 17 deletions.
35 changes: 18 additions & 17 deletions test/unit/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -18,20 +18,21 @@ cmake_minimum_required(VERSION 3.15)
# Add subdirectories.
################################################################################

add_subdirectory("acc/")
add_subdirectory("atomic/")
add_subdirectory("block/shared/")
add_subdirectory("block/sync/")
add_subdirectory("core/")
add_subdirectory("event/")
add_subdirectory("idx/")
add_subdirectory("kernel/")
add_subdirectory("math/sincos/")
add_subdirectory("mem/buf/")
add_subdirectory("mem/view/")
add_subdirectory("mem/p2p/")
add_subdirectory("meta/")
add_subdirectory("queue/")
add_subdirectory("rand/")
add_subdirectory("time/")
add_subdirectory("vec/")
ADD_SUBDIRECTORY("acc/")
ADD_SUBDIRECTORY("atomic/")
ADD_SUBDIRECTORY("block/shared/")
ADD_SUBDIRECTORY("block/sync/")
ADD_SUBDIRECTORY("core/")
ADD_SUBDIRECTORY("event/")
ADD_SUBDIRECTORY("idx/")
ADD_SUBDIRECTORY("kernel/")
ADD_SUBDIRECTORY("math/mathOps/")
ADD_SUBDIRECTORY("math/sincos/")
ADD_SUBDIRECTORY("mem/buf/")
ADD_SUBDIRECTORY("mem/view/")
ADD_SUBDIRECTORY("mem/p2p/")
ADD_SUBDIRECTORY("meta/")
ADD_SUBDIRECTORY("queue/")
ADD_SUBDIRECTORY("rand/")
ADD_SUBDIRECTORY("time/")
ADD_SUBDIRECTORY("vec/")
47 changes: 47 additions & 0 deletions test/unit/math/mathOps/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
#
# Copyright 2017-2019 Benjamin Worpitz, Jakob Krude
#
# This file is part of Alpaka.
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#

SET(_TARGET_NAME "mathOps")


append_recursive_files_add_to_src_group("src/" "src/" "cpp" _FILES_SOURCE)


message(STATUS "Disabling fast math options for math operation tests only.")
if(ALPAKA_ACC_GPU_CUDA_ENABLE)
list(REMOVE_ITEM
CUDA_NVCC_FLAGS "--ftz=true" "--prec-div=false" "--prec-sqrt=false" "--fmad=true" "--use_fast_math" "-use_fast_math")

endif()
if(ALPAKA_ACC_GPU_HIP_ENABLE)
list(REMOVE_ITEM
HIP_NVCC_FLAGS "--ftz=true" "--prec-div=false" "--prec-sqrt=false" "--fmad=true" "--use_fast_math" "-use_fast_math")
endif()


ALPAKA_ADD_EXECUTABLE(
${_TARGET_NAME}
${_FILES_SOURCE})
TARGET_INCLUDE_DIRECTORIES(
${_TARGET_NAME}
PRIVATE ${Boost_INCLUDE_DIRS})
TARGET_LINK_LIBRARIES(
${_TARGET_NAME}
PRIVATE common)
SET_TARGET_PROPERTIES(
${_TARGET_NAME}
PROPERTIES
COMPILE_OPTIONS
$<$<CXX_COMPILER_ID:clang>:"-ffp-contract=off"> # ffp-contract: https://llvm.org/docs/CompileCudaWithLLVM.html#id5
)

SET_TARGET_PROPERTIES(${_TARGET_NAME} PROPERTIES FOLDER "test/unit")

ADD_TEST(NAME ${_TARGET_NAME} COMMAND ${_TARGET_NAME} ${_ALPAKA_TEST_OPTIONS})
151 changes: 151 additions & 0 deletions test/unit/math/mathOps/include/Buffer.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
/** Copyright 2019 Jakob Krude, Benjamin Worpitz
*
* This file is part of Alpaka.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/

#pragma once

#include "Defines.hpp"
#include <alpaka/test/acc/TestAccs.hpp>
#include <ostream>

namespace alpaka {
namespace test {
namespace unit {
namespace math {

//! Provides Alpaka-style buffer with arguments' data.
//! TData can be a plain value or a complex data-structure.
//! The operator() is overloaded and returns the value from the correct Buffer,
//! either from the host (index) or device buffer (index, acc).
//! Index out of range errors are not checked.
//! @brief Encapsulates buffer initialisation and communication with Device.
//! @tparam TAcc Used accelerator, not interchangeable
//! @tparam TData The Data-type, only restricted by the alpaka-interface.
//! @tparam Tcapacity The size of the buffer.
template<
typename TAcc,
typename TData,
size_t Tcapacity
>
struct Buffer
{
using value_type = TData;
static constexpr size_t capacity = Tcapacity;
using Dim = typename alpaka::dim::traits::DimType<TAcc>::type;
using Idx = typename alpaka::idx::traits::IdxType<TAcc>::type;

// Defines using's for alpaka-buffer.
using DevAcc = alpaka::dev::Dev< TAcc >;
using DevHost = alpaka::dev::DevCpu;
using PltfHost = alpaka::pltf::Pltf< DevHost >;

using BufHost = alpaka::mem::buf::Buf<
DevHost,
TData,
Dim,
Idx
>;
using BufAcc = alpaka::mem::buf::Buf<
DevAcc,
TData,
Dim,
Idx
>;

DevHost devHost;

BufHost hostBuffer;
BufAcc devBuffer;

// Native pointer to access buffer.
TData * const pHostBuffer;
TData * const pDevBuffer;


// This constructor cant be used,
// because BufHost and BufAcc need to be initialised.
Buffer( ) = delete;

// Constructor needs to initialize all Buffer.
Buffer(const DevAcc & devAcc)
:
devHost{ alpaka::pltf::getDevByIdx< PltfHost >( 0u ) },
hostBuffer
{
alpaka::mem::buf::alloc<TData, Idx>(devHost, Tcapacity)
},
devBuffer
{
alpaka::mem::buf::alloc<TData, Idx>(devAcc, Tcapacity)
},
pHostBuffer{ alpaka::mem::view::getPtrNative( hostBuffer ) },
pDevBuffer{ alpaka::mem::view::getPtrNative( devBuffer ) }
{}

// Copy Host -> Acc.
template< typename Queue >
auto copyToDevice( Queue queue ) -> void
{
alpaka::mem::view::copy(
queue,
devBuffer,
hostBuffer,
Tcapacity
);
}

// Copy Acc -> Host.
template< typename Queue >
auto copyFromDevice( Queue queue ) -> void
{
alpaka::mem::view::copy(
queue,
hostBuffer,
devBuffer,
Tcapacity
);
}

ALPAKA_FN_ACC
auto operator()(
size_t idx,
TAcc const & acc ) const -> TData&
{
alpaka::ignore_unused(acc);
return pDevBuffer[idx];
}

ALPAKA_FN_HOST
auto operator()(
size_t idx ) const -> TData&
{
return pHostBuffer[idx];
}

ALPAKA_FN_HOST
friend std::ostream & operator<<(
std::ostream & os,
const Buffer & buffer
)
{
os << "capacity: " << capacity
<< "\n";
for( size_t i = 0; i < capacity; ++i )
{
os << i
<< ": " << buffer.pHostBuffer[i]
<< "\n";
}
return os;
}
};

} // math
} // unit
} // test
} // alpaka
139 changes: 139 additions & 0 deletions test/unit/math/mathOps/include/DataGen.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
/** Copyright 2019 Jakob Krude, Benjamin Worpitz
*
* This file is part of Alpaka.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/

#pragma once

#include "Defines.hpp"
#include <random>
#include <limits>
#include <cassert>

namespace alpaka {
namespace test {
namespace unit {
namespace math {


/**
* Fills buffer with random numbers (host-only).
*
* @tparam TData The used data-type (float || double).
* @tparam TArgs The args-buffer to be filled.
* @tparam TFunctor The used Functor-type.
* @param args The buffer that should be filled.
* @param functor The Functor, needed for ranges.
* @param seed The used seed.
*/
template<
typename TData,
typename TArgs,
typename TFunctor>
auto fillWithRndArgs(
TArgs & args,
TFunctor functor,
unsigned long const & seed
) -> void
{
/*
* Each "sub-buffer" is filled with zero and/or max and/or lowest,
* depending on the specified range (at [0] - [2]).
*
* Every switch case needs to return!
* If no switch case was matched an assert(false) will be triggered.
*
* This function is easily extendable. It is only necessary to add extra
* definitions in the switch case, for more Range-types.
*/
static_assert( TArgs::value_type::arity == TFunctor::arity,
"Buffer properties must match TFunctor::arity" );
static_assert( TArgs::capacity > 2,
"Set of args must provide > 2 entries." );
constexpr auto max = std::numeric_limits< TData >::max();
constexpr auto low = std::numeric_limits< TData >::lowest();
std::default_random_engine eng{ seed };

// These pseudo-random numbers are implementation/platform specific!
std::uniform_real_distribution< TData > dist(0,1000);
std::uniform_real_distribution< TData > distOne(-1,1);

for(size_t k = 0; k < TFunctor::arity_nr; ++k)
{
bool matchedSwitch = false;
switch( functor.ranges[k] )
{
case Range::OneNeighbourhood:
matchedSwitch = true;
for( size_t i = 0; i < TArgs::capacity; ++i )
{
args( i ).arg[k] = distOne( eng );
}
break;

case Range::PositiveOnly:
matchedSwitch = true;
args( 0 ).arg[k] = max;
for( size_t i = 1; i < TArgs::capacity; ++i )
{
args( i ).arg[k] = dist( eng ) + static_cast<TData>(1);
}
break;

case Range::PositiveAndZero:
matchedSwitch = true;
args( 0 ).arg[k] = 0.0;
args( 1 ).arg[k] = max;
for( size_t i = 2; i < TArgs::capacity; ++i )
{
args( i ).arg[k] = dist( eng );
}
break;

case Range::NotZero:
matchedSwitch = true;
args( 0 ).arg[k] = max;
args( 1 ).arg[k] = low;
for( size_t i = 2; i < TArgs::capacity; ++i )
{
TData arg;
do
{
arg = dist( eng );
}
while( std::equal_to<TData>()(arg,1) );
if( i % 2 == 0 )
args( i ).arg[k] = arg;
else
args( i ).arg[k] = -arg;
}
break;

case Range::Unrestricted:
matchedSwitch = true;
args( 0 ).arg[k] = 0.0;
args( 1 ).arg[k] = max;
args( 2 ).arg[k] = low;
for( size_t i = 3; i < TArgs::capacity; ++i )
{
if( i % 2 == 0 )
args( i ).arg[k] = dist( eng );
else
args( i ).arg[k] = -dist( eng );
}
break;
}
// disable gcc-warning "unused variable"
alpaka::ignore_unused(matchedSwitch);
assert(matchedSwitch);
}
}

} // math
} // unit
} // test
} // alpaka
Loading

0 comments on commit b5b6051

Please sign in to comment.