Commit c2f2c166 authored by Robert Maynard's avatar Robert Maynard

Test all Fancy ArrayHandles and Array Portals on every device adapter.

Fancy array handles being Counting, Implicit, Permutation, Transform, and Zip.
parent 1d170b8f
......@@ -20,7 +20,7 @@
set(unit_tests
UnitTestCudaArrayHandle.cu
UnitTestCudaArrayHandleCounting.cu
UnitTestCudaArrayHandleFancy.cu
UnitTestDeviceAdapterCuda.cu
)
vtkm_unit_tests(CUDA SOURCES ${unit_tests})
......@@ -18,84 +18,18 @@
// this software.
//============================================================================
#define VTKM_DEVICE_ADAPTER VTKM_DEVICE_ADAPTER_CUDA
#define VTKM_DEVICE_ADAPTER VTKM_DEVICE_ADAPTER_ERROR
#define BOOST_SP_DISABLE_THREADS
#include <vtkm/cont/cuda/DeviceAdapterCuda.h>
#include <vtkm/cont/ArrayHandle.h>
#include <vtkm/cont/ArrayHandleCounting.h>
#include <vtkm/worklet/DispatcherMapField.h>
#include <vtkm/worklet/WorkletMapField.h>
#include <vtkm/cont/testing/TestingFancyArrayHandles.h>
#include <vtkm/cont/cuda/internal/testing/Testing.h>
namespace ut_handle_counting{
const vtkm::Id ARRAY_SIZE = 300;
struct PassThrough : public vtkm::worklet::WorkletMapField
int UnitTestCudaArrayHandleFancy(int, char *[])
{
typedef void ControlSignature(FieldIn<>, FieldOut<>);
typedef _2 ExecutionSignature(_1);
template<class ValueType>
VTKM_EXEC_EXPORT
ValueType operator()(const ValueType &inValue) const
{ return inValue; }
};
template< typename ValueType >
struct CountingTest
{
void operator()(const ValueType v) const
{
const ValueType start = v;
const ValueType end = start + ARRAY_SIZE;
vtkm::cont::ArrayHandleCounting< ValueType > implicit =
vtkm::cont::make_ArrayHandleCounting(start, end);
vtkm::cont::ArrayHandle< ValueType > result;
vtkm::worklet::DispatcherMapField< ut_handle_counting::PassThrough > dispatcher;
dispatcher.Invoke(implicit, result);
//verify that the control portal works
for(int i=v; i < ARRAY_SIZE; ++i)
{
const ValueType result_v = result.GetPortalConstControl().Get(i);
const ValueType correct_value = v + ValueType(i);
VTKM_TEST_ASSERT(result_v == correct_value, "Counting Handle Failed");
}
}
};
template <typename T>
void RunCountingTest(const T t)
{
CountingTest<T> tests;
tests(t);
}
void TestArrayHandleCounting()
{
RunCountingTest( vtkm::Id(42) );
RunCountingTest( vtkm::Float32(3) );
// RunCountingTest( vtkm::Vec< vtkm::Float32, 3>() );
int result = vtkm::cont::testing::TestingFancyArrayHandles
<vtkm::cont::DeviceAdapterTagCuda>::Run();
return vtkm::cont::cuda::internal::Testing::CheckCudaBeforeExit(result);
}
} // ut_handle_counting namespace
int UnitTestCudaArrayHandleCounting(int, char *[])
{
return vtkm::cont::cuda::internal::Testing::Run(
ut_handle_counting::TestArrayHandleCounting);
}
......@@ -21,6 +21,7 @@
set(headers
Testing.h
TestingDeviceAdapter.h
TestingFancyArrayHandles.h
)
vtkm_declare_headers(${headers})
......@@ -29,6 +30,7 @@ set(unit_tests
UnitTestArrayHandle.cxx
UnitTestArrayHandleCompositeVector.cxx
UnitTestArrayHandleCounting.cxx
UnitTestArrayHandleFancy.cxx
UnitTestArrayHandleImplicit.cxx
UnitTestArrayHandlePermutation.cxx
UnitTestArrayHandleTransform.cxx
......
//=============================================================================
//
// Copyright (c) Kitware, Inc.
// All rights reserved.
// See LICENSE.txt for details.
//
// This software is distributed WITHOUT ANY WARRANTY; without even
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the above copyright notice for more information.
//
// Copyright 2015 Sandia Corporation.
// Copyright 2015 UT-Battelle, LLC.
// Copyright 2015. Los Alamos National Security
//
// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
// the U.S. Government retains certain rights in this software.
// Under the terms of Contract DE-AC52-06NA25396 with Los Alamos National
// Laboratory (LANL), the U.S. Government retains certain rights in
// this software.
//
//=============================================================================
#ifndef vtk_m_cont_testing_TestingFancyArrayHandles_h
#define vtk_m_cont_testing_TestingFancyArrayHandles_h
#include <vtkm/cont/ArrayHandleCounting.h>
#include <vtkm/cont/ArrayHandleImplicit.h>
#include <vtkm/cont/ArrayHandlePermutation.h>
#include <vtkm/cont/ArrayHandleTransform.h>
#include <vtkm/cont/ArrayHandleZip.h>
#include <vtkm/VecTraits.h>
#include <vtkm/worklet/DispatcherMapField.h>
#include <vtkm/worklet/WorkletMapField.h>
#include <vtkm/cont/testing/Testing.h>
namespace fancy_array_detail
{
template<typename T>
class IncrementBy2
{
public:
VTKM_EXEC_CONT_EXPORT
IncrementBy2(): Value(0)
{
}
VTKM_EXEC_CONT_EXPORT
explicit IncrementBy2(vtkm::Id index):
Value(0) //required before we increment
{
VTKM_ASSERT_CONT(index >= 0);
for (vtkm::Id i = 0; i < index; i++)
{ this->Value++; this->Value++; }
}
VTKM_EXEC_CONT_EXPORT
IncrementBy2 operator+(const IncrementBy2 &rhs) const
{
//don't want to trigger the vtkm::Id constructor
//when making a copy and cause this to be IncrementBy4
IncrementBy2 newValue;
newValue.Value = this->Value + rhs.Value;
return newValue;
}
VTKM_EXEC_CONT_EXPORT
bool operator==(const IncrementBy2 &other) const
{
return this->Value == other.Value;
}
VTKM_EXEC_CONT_EXPORT
IncrementBy2 &operator++()
{
this->Value++;
this->Value++;
return *this;
}
VTKM_CONT_EXPORT
friend std::ostream& operator<<(std::ostream &os, const IncrementBy2 &v)
{ os << v.Value; return os; }
T Value;
};
template<typename ValueType>
struct IndexSquared
{
VTKM_EXEC_CONT_EXPORT
ValueType operator()(vtkm::Id i) const
{ return ValueType( vtkm::dot(i,i) ); }
};
template<typename ValueType>
struct ValueSquared
{
template<typename U>
VTKM_EXEC_CONT_EXPORT
ValueType operator()(U u) const
{ return vtkm::dot(u, u); }
template<typename U>
VTKM_EXEC_CONT_EXPORT
ValueType operator()( ::fancy_array_detail::IncrementBy2<U> u) const
{ return ValueType( vtkm::dot(u.Value, u.Value) ); }
};
}
namespace vtkm {
// Allows us to use vec traits with IncrementBy2, will make look like
// a vector of a single component
template< typename T >
struct VecTraits< ::fancy_array_detail::IncrementBy2<T> > :
public vtkm::internal::VecTraitsBasic< ::fancy_array_detail::IncrementBy2<T> >
{ };
}
namespace vtkm { namespace testing {
template<typename T>
struct TypeName< ::fancy_array_detail::IncrementBy2<T> >
{
static std::string Name()
{
std::stringstream stream;
stream << "fancy_array_detail::IncrementBy2< " << TypeName<T>::Name() << " >";
return stream.str();
}
};
} }
namespace vtkm {
namespace cont {
namespace testing {
/// This class has a single static member, Run, that tests that all Fancy Array
/// Handles work with the given DeviceAdapter
///
template<class DeviceAdapterTag>
struct TestingFancyArrayHandles
{
private:
static const int ARRAY_SIZE = 10;
public:
struct PassThrough : public vtkm::worklet::WorkletMapField
{
typedef void ControlSignature(FieldIn<>, FieldOut<>);
typedef _2 ExecutionSignature(_1);
template<class ValueType>
VTKM_EXEC_EXPORT
ValueType operator()(const ValueType &inValue) const
{ return inValue; }
};
private:
struct TestZipAsInput
{
template< typename KeyType, typename ValueType >
VTKM_CONT_EXPORT
void operator()(vtkm::Pair<KeyType,ValueType> vtkmNotUsed(pair)) const
{
typedef vtkm::Pair< KeyType, ValueType > PairType;
KeyType testKeys[ARRAY_SIZE];
ValueType testValues[ARRAY_SIZE];
for(vtkm::Id i=0; i < ARRAY_SIZE; ++i)
{
testKeys[i] = KeyType(ARRAY_SIZE - i);
testValues[i] = ValueType(i);
}
vtkm::cont::ArrayHandle< KeyType > keys =
vtkm::cont::make_ArrayHandle(testKeys, ARRAY_SIZE);
vtkm::cont::ArrayHandle< ValueType > values =
vtkm::cont::make_ArrayHandle(testValues, ARRAY_SIZE);
vtkm::cont::ArrayHandleZip<
vtkm::cont::ArrayHandle< KeyType >,
vtkm::cont::ArrayHandle< ValueType > > zip =
vtkm::cont::make_ArrayHandleZip(keys, values);
vtkm::cont::ArrayHandle< PairType > result;
vtkm::worklet::DispatcherMapField< PassThrough, DeviceAdapterTag > dispatcher;
dispatcher.Invoke(zip, result);
//verify that the control portal works
for(int i=0; i < ARRAY_SIZE; ++i)
{
const PairType result_v = result.GetPortalConstControl().Get(i);
const PairType correct_value( KeyType(ARRAY_SIZE - i), ValueType(i) );
VTKM_TEST_ASSERT(result_v == correct_value, "ArrayHandleZip Failed as input");
}
}
};
struct TestZipAsOutput
{
template< typename KeyType, typename ValueType >
VTKM_CONT_EXPORT
void operator()(vtkm::Pair<KeyType,ValueType> vtkmNotUsed(pair)) const
{
typedef vtkm::Pair< KeyType, ValueType > PairType;
PairType testKeysAndValues[ARRAY_SIZE];
for(vtkm::Id i=0; i < ARRAY_SIZE; ++i)
{
testKeysAndValues[i] = PairType(KeyType(ARRAY_SIZE - i), ValueType(i) );
}
vtkm::cont::ArrayHandle< PairType > input =
vtkm::cont::make_ArrayHandle(testKeysAndValues, ARRAY_SIZE);
vtkm::cont::ArrayHandle< KeyType > result_keys;
vtkm::cont::ArrayHandle< ValueType > result_values;
vtkm::cont::ArrayHandleZip<
vtkm::cont::ArrayHandle< KeyType >,
vtkm::cont::ArrayHandle< ValueType > > result_zip =
vtkm::cont::make_ArrayHandleZip(result_keys, result_values);
vtkm::worklet::DispatcherMapField< PassThrough, DeviceAdapterTag > dispatcher;
dispatcher.Invoke(input, result_zip);
//now the two arrays we have zipped should have data inside them
for(int i=0; i < ARRAY_SIZE; ++i)
{
const KeyType result_key = result_keys.GetPortalConstControl().Get(i);
const ValueType result_value = result_values.GetPortalConstControl().Get(i);
VTKM_TEST_ASSERT(result_key == KeyType(ARRAY_SIZE - i), "ArrayHandleZip Failed as input");
VTKM_TEST_ASSERT(result_value == ValueType(i), "ArrayHandleZip Failed as input");
}
}
};
struct TestCountingAsInput
{
template< typename ValueType >
VTKM_CONT_EXPORT void operator()(const ValueType vtkmNotUsed(v)) const
{
const vtkm::Id length = ARRAY_SIZE;
//need to initialize the start value or else vectors will have
//random values to start
vtkm::Id initial_value(0);
const ValueType start = ValueType(initial_value);
vtkm::cont::ArrayHandleCounting< ValueType > counting =
vtkm::cont::make_ArrayHandleCounting(start, length);
vtkm::cont::ArrayHandle< ValueType > result;
vtkm::worklet::DispatcherMapField< PassThrough, DeviceAdapterTag > dispatcher;
dispatcher.Invoke(counting, result);
//verify that the control portal works
for(vtkm::Id i=0; i < length; ++i)
{
const ValueType result_v = result.GetPortalConstControl().Get(i);
const ValueType correct_value = ValueType(initial_value + i);
const ValueType control_value = counting.GetPortalConstControl().Get(i);
VTKM_TEST_ASSERT(result_v == correct_value, "Counting Handle Failed");
VTKM_TEST_ASSERT(result_v == control_value, "Counting Handle Failed");
}
}
};
struct TestImplicitAsInput
{
template< typename ValueType>
VTKM_CONT_EXPORT void operator()(const ValueType vtkmNotUsed(v)) const
{
const vtkm::Id length = ARRAY_SIZE;
typedef ::fancy_array_detail::IndexSquared<ValueType> FunctorType;
FunctorType functor;
vtkm::cont::ArrayHandleImplicit< ValueType, FunctorType > implicit =
vtkm::cont::make_ArrayHandleImplicit<ValueType>(functor, length);
vtkm::cont::ArrayHandle< ValueType > result;
vtkm::worklet::DispatcherMapField< PassThrough, DeviceAdapterTag > dispatcher;
dispatcher.Invoke(implicit, result);
//verify that the control portal works
for(vtkm::Id i=0; i < length; ++i)
{
const ValueType result_v = result.GetPortalConstControl().Get(i);
const ValueType correct_value = functor( i );
const ValueType control_value = implicit.GetPortalConstControl().Get(i);
VTKM_TEST_ASSERT(result_v == correct_value, "Implicit Handle Failed");
VTKM_TEST_ASSERT(result_v == control_value, "Implicit Handle Failed");
}
}
};
struct TestPermutationAsInput
{
template< typename ValueType>
VTKM_CONT_EXPORT void operator()(const ValueType vtkmNotUsed(v)) const
{
const vtkm::Id length = ARRAY_SIZE;
typedef ::fancy_array_detail::IndexSquared<ValueType> FunctorType;
typedef vtkm::cont::ArrayHandleCounting< vtkm::Id > KeyHandleType;
typedef vtkm::cont::ArrayHandleImplicit< ValueType,
FunctorType > ValueHandleType;
typedef vtkm::cont::ArrayHandlePermutation< KeyHandleType,
ValueHandleType
> PermutationHandleType;
FunctorType functor;
for( vtkm::Id start_pos = 0; start_pos < (length-10); start_pos+=10)
{
const vtkm::Id counting_length = length - start_pos;
KeyHandleType counting =
vtkm::cont::make_ArrayHandleCounting<vtkm::Id>(start_pos,
counting_length);
ValueHandleType implicit =
vtkm::cont::make_ArrayHandleImplicit<ValueType>(functor,
length);
PermutationHandleType permutation =
vtkm::cont::make_ArrayHandlePermutation(counting,
implicit);
vtkm::cont::ArrayHandle< ValueType > result;
vtkm::worklet::DispatcherMapField< PassThrough, DeviceAdapterTag > dispatcher;
dispatcher.Invoke(permutation, result);
//verify that the control portal works
for(vtkm::Id i=0; i <counting_length; ++i)
{
const vtkm::Id value_index = i;
const vtkm::Id key_index = start_pos + i;
const ValueType result_v = result.GetPortalConstControl().Get( value_index );
const ValueType correct_value = implicit.GetPortalConstControl().Get( key_index );
const ValueType control_value = permutation.GetPortalConstControl().Get( value_index );
VTKM_TEST_ASSERT(result_v == correct_value, "Implicit Handle Failed");
VTKM_TEST_ASSERT(result_v == control_value, "Implicit Handle Failed");
}
}
}
};
struct TestTransformAsInput
{
template< typename ValueType>
VTKM_CONT_EXPORT void operator()(const ValueType vtkmNotUsed(v)) const
{
typedef typename vtkm::VecTraits<ValueType>::ComponentType OutputValueType;
typedef fancy_array_detail::ValueSquared<OutputValueType> FunctorType;
const vtkm::Id length = ARRAY_SIZE;
FunctorType functor;
vtkm::cont::ArrayHandle<ValueType> input;
vtkm::cont::ArrayHandleTransform<
OutputValueType,
vtkm::cont::ArrayHandle<ValueType>,
FunctorType> transformed =
vtkm::cont::make_ArrayHandleTransform<OutputValueType>(input,
functor);
typedef typename vtkm::cont::ArrayHandle<ValueType>::PortalControl Portal;
input.Allocate(length);
Portal portal = input.GetPortalControl();
vtkm::Id initial_value(length);
for(vtkm::Id i=0; i < length; ++i)
{
portal.Set(i, ValueType(initial_value - i) );
}
vtkm::cont::ArrayHandle< OutputValueType > result;
vtkm::worklet::DispatcherMapField< PassThrough, DeviceAdapterTag > dispatcher;
dispatcher.Invoke(transformed, result);
//verify that the control portal works
for(vtkm::Id i=0; i < length; ++i)
{
const OutputValueType result_v = result.GetPortalConstControl().Get(i);
const OutputValueType correct_value = transformed.GetPortalConstControl().Get(i);
VTKM_TEST_ASSERT(result_v == correct_value, "Transform Handle Failed");
}
}
};
struct TestCountingTransformAsInput
{
template< typename ValueType>
VTKM_CONT_EXPORT void operator()(const ValueType vtkmNotUsed(v)) const
{
typedef typename vtkm::VecTraits<ValueType>::ComponentType OutputValueType;
typedef fancy_array_detail::ValueSquared<OutputValueType> FunctorType;
vtkm::Id length = ARRAY_SIZE;
FunctorType functor;
//need to initialize the start value or else vectors will have
//random values to start
vtkm::Id initial_value(0);
const ValueType start = ValueType(initial_value);
vtkm::cont::ArrayHandleCounting< ValueType > counting =
vtkm::cont::make_ArrayHandleCounting(start,
length);
vtkm::cont::ArrayHandleTransform<
OutputValueType,
vtkm::cont::ArrayHandleCounting<ValueType>,
FunctorType>
countingTransformed =
vtkm::cont::make_ArrayHandleTransform<OutputValueType>(counting,
functor);
vtkm::cont::ArrayHandle< OutputValueType > result;
vtkm::worklet::DispatcherMapField< PassThrough, DeviceAdapterTag > dispatcher;
dispatcher.Invoke(countingTransformed, result);
//verify that the control portal works
for(vtkm::Id i=0; i < length; ++i)
{
const OutputValueType result_v = result.GetPortalConstControl().Get(i);
const OutputValueType correct_value = countingTransformed.GetPortalConstControl().Get(i);
VTKM_TEST_ASSERT(result_v == correct_value, "Transform Counting Handle Failed");
}
}
};
struct ZipTypesToTest
: vtkm::ListTagBase< vtkm::Pair< vtkm::UInt8, vtkm::Id >,
vtkm::Pair< vtkm::Int32, vtkm::Vec< vtkm::Float32, 3> >,
vtkm::Pair< vtkm::Float64, vtkm::Vec< vtkm::UInt8, 4> >,
vtkm::Pair< vtkm::Vec<vtkm::Float32,3>, vtkm::Vec<vtkm::Int8, 4> >,
vtkm::Pair< vtkm::Vec<vtkm::Float64,2>, vtkm::Int32 >
>
{ };
struct HandleTypesToTest
: vtkm::ListTagBase< vtkm::Int8,
vtkm::UInt8,
vtkm::Int32,
vtkm::Int64,
vtkm::Vec<vtkm::Int32,2>,
vtkm::Vec<vtkm::UInt8,4>,
vtkm::Float32,
vtkm::Float64,
vtkm::Vec<vtkm::Float64,3>,
vtkm::Vec<vtkm::Float32,4>,
::fancy_array_detail::IncrementBy2 < vtkm::Int32 >,
::fancy_array_detail::IncrementBy2 < vtkm::Float32 >
>
{ };
struct TestAll
{
VTKM_CONT_EXPORT void operator()() const
{
std::cout << "Doing FancyArrayHandle tests" << std::endl;
std::cout << "-------------------------------------------" << std::endl;
std::cout << "Testing ArrayHandleZip as Input" << std::endl;
vtkm::testing::Testing::TryTypes(