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

NEW Added tests for existing math operators #847

Merged
merged 2 commits into from
Apr 22, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions test/unit/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ 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/")
Expand Down
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{
static_cast< std::default_random_engine::result_type >( 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