Merge branch 'add_serial_deviceAdapter'

This commit is contained in:
Robert Maynard 2014-02-11 16:21:02 -05:00
commit 5b8bec5ecd
22 changed files with 3911 additions and 1 deletions

@ -0,0 +1,144 @@
//============================================================================
// 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 2014 Sandia Corporation.
// Copyright 2014 UT-Battelle, LLC.
// Copyright 2014. 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 vtkm_cont_ArrayHandleCounting_h
#define vtkm_cont_ArrayHandleCounting_h
#include <vtkm/cont/ArrayContainerControlImplicit.h>
#include <vtkm/cont/ArrayHandle.h>
#include <vtkm/cont/internal/IteratorFromArrayPortal.h>
namespace vtkm {
namespace cont {
namespace internal {
/// \brief An implicit array portal that returns an counting value.
template <class CountingValueType>
class ArrayPortalCounting
{
public:
typedef CountingValueType ValueType;
VTKM_EXEC_CONT_EXPORT
ArrayPortalCounting() :
StartingValue(),
NumberOfValues(0)
{ }
VTKM_EXEC_CONT_EXPORT
ArrayPortalCounting(ValueType startingValue, vtkm::Id numValues) :
StartingValue(startingValue),
NumberOfValues(numValues)
{ }
template<typename OtherValueType>
VTKM_EXEC_CONT_EXPORT
ArrayPortalCounting(const ArrayPortalCounting<OtherValueType> &src)
: StartingValue(src.StartingValue),
NumberOfValues(src.NumberOfValues)
{ }
template<typename OtherValueType>
VTKM_EXEC_CONT_EXPORT
ArrayPortalCounting<ValueType> &operator=(
const ArrayPortalCounting<OtherValueType> &src)
{
this->StartingValue = src.StartingValue;
this->NumberOfValues = src.NumberOfValues;
return *this;
}
VTKM_EXEC_CONT_EXPORT
vtkm::Id GetNumberOfValues() const { return this->NumberOfValues; }
VTKM_EXEC_CONT_EXPORT
ValueType Get(vtkm::Id index) const { return StartingValue+index; }
typedef vtkm::cont::internal::IteratorFromArrayPortal<
ArrayPortalCounting < CountingValueType> > IteratorType;
VTKM_CONT_EXPORT
IteratorType GetIteratorBegin() const
{
return IteratorType(*this);
}
VTKM_CONT_EXPORT
IteratorType GetIteratorEnd() const
{
return IteratorType(*this, this->NumberOfValues);
}
private:
CountingValueType StartingValue;
vtkm::Id NumberOfValues;
};
/// A convenience class that provides a typedef to the appropriate tag for
/// a counting array container.
template<typename ConstantValueType>
struct ArrayHandleCountingTraits
{
typedef vtkm::cont::ArrayContainerControlTagImplicit<
vtkm::cont::internal::ArrayPortalCounting<ConstantValueType> > Tag;
};
} // namespace internal
/// ArrayHandleCountings is a specialization of ArrayHandle. By default it
/// contains a increment value, that is increment for each step between zero
/// and the passed in length
template <typename CountingValueType>
class ArrayHandleCounting
: public vtkm::cont::ArrayHandle <
CountingValueType,
typename internal::ArrayHandleCountingTraits<CountingValueType>::Tag
>
{
typedef vtkm::cont::ArrayHandle <
CountingValueType,
typename internal::ArrayHandleCountingTraits<CountingValueType>::Tag
> Superclass;
public:
ArrayHandleCounting(CountingValueType startingValue, vtkm::Id length)
:Superclass(typename Superclass::PortalConstControl(startingValue, length))
{
}
ArrayHandleCounting():Superclass() {}
};
/// A convenience function for creating an ArrayHandleCounting. It takes the
/// value to start counting from and and the number of times to increment.
template<typename CountingValueType>
VTKM_CONT_EXPORT
vtkm::cont::ArrayHandleCounting<CountingValueType>
make_ArrayHandleCounting(CountingValueType startingValue,
vtkm::Id length)
{
return vtkm::cont::ArrayHandleCounting<CountingValueType>(startingValue,
length);
}
}
} // namespace vtkm::cont
#endif //vtkm_cont_ArrayHandleCounting_h

@ -27,6 +27,8 @@ set(headers
ArrayHandle.h
ArrayPortal.h
Assert.h
DeviceAdapter.h
DeviceAdapterSerial.h
Error.h
ErrorControl.h
ErrorControlAssert.h

73
vtkm/cont/DeviceAdapter.h Normal file

@ -0,0 +1,73 @@
//============================================================================
// 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 2014 Sandia Corporation.
// Copyright 2014 UT-Battelle, LLC.
// Copyright 2014. 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 vtkm_cont_DeviceAdapter_h
#define vtkm_cont_DeviceAdapter_h
// These are listed in non-alphabetical order because this is the conceptual
// order in which the sub-files are loaded. (But the compile should still
// succeed of the order is changed.)
#include <vtkm/cont/internal/DeviceAdapterTag.h>
#include <vtkm/cont/internal/ArrayManagerExecution.h>
#include <vtkm/cont/internal/DeviceAdapterAlgorithm.h>
namespace vtkm {
namespace cont {
#ifdef VTKM_DOXYGEN_ONLY
/// \brief A tag specifying the interface between the control and execution environments.
///
/// A DeviceAdapter tag specifies a set of functions and classes that provide
/// mechanisms to run algorithms on a type of parallel device. The tag
/// DeviceAdapterTag___ does not actually exist. Rather, this documentation is
/// provided to describe the interface for a DeviceAdapter. Loading the
/// dax/cont/DeviceAdapter.h header file will set a default device adapter
/// appropriate for the current compile environment. You can specify the
/// default device adapter by first setting the \c VTKM_DEVICE_ADAPTER macro.
/// Valid values for \c VTKM_DEVICE_ADAPTER are the following:
///
/// \li \c VTKM_DEVICE_ADAPTER_SERIAL Runs all algorithms in serial. Can be
/// helpful for debugging.
/// \li \c VTKM_DEVICE_ADAPTER_CUDA Dispatches and runs algorithms on a GPU
/// using CUDA. Must be compiling with a CUDA compiler (nvcc).
/// \li \c VTKM_DEVICE_ADAPTER_OPENMP Dispatches an algorithm over multiple
/// CPU cores using OpenMP compiler directives. Must be compiling with an
/// OpenMP-compliant compiler with OpenMP pragmas enabled.
/// \li \c VTKM_DEVICE_ADAPTER_TBB Dispatches and runs algorithms on multiple
/// threads using the Intel Threading Building Blocks (TBB) libraries. Must
/// have the TBB headers available and the resulting code must be linked with
/// the TBB libraries.
///
/// See the ArrayManagerExecution.h and DeviceAdapterAlgorithm.h files for
/// documentation on all the functions and classes that must be
/// overloaded/specialized to create a new device adapter.
///
struct DeviceAdapterTag___ { };
#endif //VTKM_DOXYGEN_ONLY
namespace internal {
} // namespace internal
}
} // namespace vtkm::cont
#endif //vtkm_cont_DeviceAdapter_h

@ -0,0 +1,27 @@
//============================================================================
// 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 2014 Sandia Corporation.
// Copyright 2014 UT-Battelle, LLC.
// Copyright 2014. 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 vtkm_cont_DeviceAdapterSerial_h
#define vtkm_cont_DeviceAdapterSerial_h
#include <vtkm/cont/internal/DeviceAdapterTagSerial.h>
#include <vtkm/cont/internal/ArrayManagerExecutionSerial.h>
#include <vtkm/cont/internal/DeviceAdapterAlgorithmSerial.h>
#endif //vtkm_cont_DeviceAdapterSerial_h

@ -26,6 +26,13 @@ set(headers
ArrayPortalFromIterators.h
ArrayPortalShrink.h
ArrayTransfer.h
DeviceAdapterAlgorithm.h
DeviceAdapterAlgorithmGeneral.h
DeviceAdapterAlgorithmSerial.h
DeviceAdapterError.h
DeviceAdapterTag.h
DeviceAdapterTagSerial.h
IteratorFromArrayPortal.h
)
vtkm_declare_headers(${headers})

@ -0,0 +1,404 @@
//============================================================================
// 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 2014 Sandia Corporation.
// Copyright 2014 UT-Battelle, LLC.
// Copyright 2014. 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 vtkm_cont_internal_DeviceAdapterAlgorithm_h
#define vtkm_cont_internal_DeviceAdapterAlgorithm_h
#include <vtkm/Types.h>
#include <vtkm/cont/internal/ArrayManagerExecution.h>
#include <vtkm/cont/internal/DeviceAdapterTag.h>
#ifndef _WIN32
#include <limits.h>
#include <sys/time.h>
#include <unistd.h>
#endif
namespace vtkm {
namespace cont {
/// \brief Struct containing device adapter algorithms.
///
/// This struct, templated on the device adapter tag, comprises static methods
/// that implement the algorithms provided by the device adapter. The default
/// struct is not implemented. Device adapter implementations must specialize
/// the template.
///
template<class DeviceAdapterTag>
struct DeviceAdapterAlgorithm
#ifdef VTKM_DOXYGEN_ONLY
{
/// \brief Copy the contents of one ArrayHandle to another
///
/// Copies the contents of \c input to \c output. The array \c to will be
/// allocated to the appropriate size.
///
template<typename T, class CIn, class COut>
VTKM_CONT_EXPORT static void Copy(
const vtkm::cont::ArrayHandle<T, CIn, DeviceAdapterTag> &input,
vtkm::cont::ArrayHandle<T, COut, DeviceAdapterTag> &output);
/// \brief Output is the first index in input for each item in values that wouldn't alter the ordering of input
///
/// LowerBounds is a vectorized search. From each value in \c values it finds
/// the first place the item can be inserted in the ordered \c input array and
/// stores the index in \c output.
///
/// \par Requirements:
/// \arg \c input must already be sorted
///
template<typename T, class CIn, class CVal, class COut>
VTKM_CONT_EXPORT static void LowerBounds(
const vtkm::cont::ArrayHandle<T,CIn,DeviceAdapterTag>& input,
const vtkm::cont::ArrayHandle<T,CVal,DeviceAdapterTag>& values,
vtkm::cont::ArrayHandle<vtkm::Id,COut,DeviceAdapterTag>& output);
/// \brief Output is the first index in input for each item in values that wouldn't alter the ordering of input
///
/// LowerBounds is a vectorized search. From each value in \c values it finds
/// the first place the item can be inserted in the ordered \c input array and
/// stores the index in \c output. Uses the custom comparison functor to
/// determine the correct location for each item.
///
/// \par Requirements:
/// \arg \c input must already be sorted
///
template<typename T, class CIn, class CVal, class COut, class Compare>
VTKM_CONT_EXPORT static void LowerBounds(
const vtkm::cont::ArrayHandle<T,CIn,DeviceAdapterTag>& input,
const vtkm::cont::ArrayHandle<T,CVal,DeviceAdapterTag>& values,
vtkm::cont::ArrayHandle<vtkm::Id,COut,DeviceAdapterTag>& output,
Compare comp);
/// \brief A special version of LowerBounds that does an in place operation.
///
/// This version of lower bounds performs an in place operation where each
/// value in the \c values_output array is replaced by the index in \c input
/// where it occurs. Because this is an in place operation, the type of the
/// arrays is limited to vtkm::Id.
///
template<class CIn, class COut>
VTKM_CONT_EXPORT static void LowerBounds(
const vtkm::cont::ArrayHandle<vtkm::Id,CIn,DeviceAdapterTag>& input,
vtkm::cont::ArrayHandle<vtkm::Id,COut,DeviceAdapterTag>& values_output);
/// \brief Compute an inclusive prefix sum operation on the input ArrayHandle.
///
/// Computes an inclusive prefix sum operation on the \c input ArrayHandle,
/// storing the results in the \c output ArrayHandle. InclusiveScan is
/// similiar to the stl partial sum function, exception that InclusiveScan
/// doesn't do a serial sumnation. This means that if you have defined a
/// custom plus operator for T it must be associative, or you will get
/// inconsistent results. When the input and output ArrayHandles are the same
/// ArrayHandle the operation will be done inplace.
///
/// \return The total sum.
///
template<typename T, class CIn, class COut>
VTKM_CONT_EXPORT static T ScanInclusive(
const vtkm::cont::ArrayHandle<T,CIn,DeviceAdapterTag> &input,
vtkm::cont::ArrayHandle<T,COut,DeviceAdapterTag>& output);
/// \brief Compute an exclusive prefix sum operation on the input ArrayHandle.
///
/// Computes an exclusive prefix sum operation on the \c input ArrayHandle,
/// storing the results in the \c output ArrayHandle. ExclusiveScan is
/// similiar to the stl partial sum function, exception that ExclusiveScan
/// doesn't do a serial sumnation. This means that if you have defined a
/// custom plus operator for T it must be associative, or you will get
/// inconsistent results. When the input and output ArrayHandles are the same
/// ArrayHandle the operation will be done inplace.
///
/// \return The total sum.
///
template<typename T, class CIn, class COut>
VTKM_CONT_EXPORT static T ScanExclusive(
const vtkm::cont::ArrayHandle<T,CIn,DeviceAdapterTag> &input,
vtkm::cont::ArrayHandle<T,COut,DeviceAdapterTag>& output);
/// \brief Schedule many instances of a function to run on concurrent threads.
///
/// Calls the \c functor on several threads. This is the function used in the
/// control environment to spawn activity in the execution environment. \c
/// functor is a function-like object that can be invoked with the calling
/// specification <tt>functor(vtkm::Id index)</tt>. It also has a method called
/// from the control environment to establish the error reporting buffer with
/// the calling specification <tt>functor.SetErrorMessageBuffer(const
/// vtkm::exec::internal::ErrorMessageBuffer &errorMessage)</tt>. This object
/// can be stored in the functor's state such that if RaiseError is called on
/// it in the execution environment, an ErrorExecution will be thrown from
/// Schedule.
///
/// The argument of the invoked functor uniquely identifies the thread or
/// instance of the invocation. There should be one invocation for each index
/// in the range [0, \c numInstances].
///
template<class Functor>
VTKM_CONT_EXPORT static void Schedule(Functor functor,
vtkm::Id numInstances);
/// \brief Schedule many instances of a function to run on concurrent threads.
///
/// Calls the \c functor on several threads. This is the function used in the
/// control environment to spawn activity in the execution environment. \c
/// functor is a function-like object that can be invoked with the calling
/// specification <tt>functor(vtkm::Id3 index)</tt> or <tt>functor(vtkm::Id
/// index)</tt>. It also has a method called from the control environment to
/// establish the error reporting buffer with the calling specification
/// <tt>functor.SetErrorMessageBuffer(const
/// vtkm::exec::internal::ErrorMessageBuffer &errorMessage)</tt>. This object
/// can be stored in the functor's state such that if RaiseError is called on
/// it in the execution environment, an ErrorExecution will be thrown from
/// Schedule.
///
/// The argument of the invoked functor uniquely identifies the thread or
/// instance of the invocation. It is at the device adapter's discretion
/// whether to schedule on 1D or 3D indices, so the functor should have an
/// operator() overload for each index type. If 3D indices are used, there is
/// one invocation for every i, j, k value between [0, 0, 0] and \c rangeMax.
/// If 1D indices are used, this Schedule behaves as if <tt>Schedule(functor,
/// rangeMax[0]*rangeMax[1]*rangeMax[2])</tt> were called.
///
template<class Functor, class IndiceType>
VTKM_CONT_EXPORT static void Schedule(Functor functor,
vtkm::Id3 rangeMax);
/// \brief Unstable ascending sort of input array.
///
/// Sorts the contents of \c values so that they in ascending value. Doesn't
/// guarantee stability
///
template<typename T, class Container>
VTKM_CONT_EXPORT static void Sort(
vtkm::cont::ArrayHandle<T,Container,DeviceAdapterTag> &values);
/// \brief Unstable ascending sort of input array.
///
/// Sorts the contents of \c values so that they in ascending value based
/// on the custom compare functor.
///
template<typename T, class Container, class Compare>
VTKM_CONT_EXPORT static void Sort(
vtkm::cont::ArrayHandle<T,Container,DeviceAdapterTag> &values,
Compare comp);
/// \brief Performs stream compaction to remove unwanted elements in the input array. Output becomes the index values of input that are valid.
///
/// Calls the parallel primitive function of stream compaction on the \c
/// input to remove unwanted elements. The result of the stream compaction is
/// placed in \c output. The \c input values are used as the stream
/// compaction stencil while \c input indices are used as the values to place
/// into \c ouput. The size of \c output will be modified after this call as
/// we can't know the number of elements that will be removed by the stream
/// compaction algorithm.
///
template<typename T, class CStencil, class COut>
VTKM_CONT_EXPORT static void StreamCompact(
const vtkm::cont::ArrayHandle<T,CStencil,DeviceAdapterTag> &stencil,
vtkm::cont::ArrayHandle<vtkm::Id,COut,DeviceAdapterTag> &output);
/// \brief Performs stream compaction to remove unwanted elements in the input array.
///
/// Calls the parallel primitive function of stream compaction on the \c
/// input to remove unwanted elements. The result of the stream compaction is
/// placed in \c output. The values in \c stencil are used as the stream
/// compaction stencil while \c input values are placed into \c ouput. The
/// size of \c output will be modified after this call as we can't know the
/// number of elements that will be removed by the stream compaction
/// algorithm.
///
template<typename T, typename U, class CIn, class CStencil, class COut>
VTKM_CONT_EXPORT static void StreamCompact(
const vtkm::cont::ArrayHandle<T,CIn,DeviceAdapterTag> &input,
const vtkm::cont::ArrayHandle<U,CStencil,DeviceAdapterTag> &stencil,
vtkm::cont::ArrayHandle<T,COut,DeviceAdapterTag> &output);
/// \brief Completes any asynchronous operations running on the device.
///
/// Waits for any asynchronous operations running on the device to complete.
///
VTKM_CONT_EXPORT static void Synchronize();
/// \brief Reduce an array to only the unique values it contains
///
/// Removes all duplicate values in \c values that are adjacent to each
/// other. Which means you should sort the input array unless you want
/// duplicate values that aren't adjacent. Note the values array size might
/// be modified by this operation.
///
template<typename T, class Container>
VTKM_CONT_EXPORT static void Unique(
vtkm::cont::ArrayHandle<T,Container,DeviceAdapterTag>& values);
/// \brief Reduce an array to only the unique values it contains
///
/// Removes all duplicate values in \c values that are adjacent to each
/// other. Which means you should sort the input array unless you want
/// duplicate values that aren't adjacent. Note the values array size might
/// be modified by this operation.
///
/// Uses the custom binary predicate Comparison to determine if something
/// is unique. The predicate must return true if the two items are the same.
///
template<typename T, class Container, class Compare>
VTKM_CONT_EXPORT static void Unique(
vtkm::cont::ArrayHandle<T,Container,DeviceAdapterTag>& values,
Compare comp);
/// \brief Output is the last index in input for each item in values that wouldn't alter the ordering of input
///
/// UpperBounds is a vectorized search. From each value in \c values it finds
/// the last place the item can be inserted in the ordered \c input array and
/// stores the index in \c output.
///
/// \par Requirements:
/// \arg \c input must already be sorted
///
template<typename T, class CIn, class CVal, class COut>
VTKM_CONT_EXPORT static void UpperBounds(
const vtkm::cont::ArrayHandle<T,CIn,DeviceAdapterTag___>& input,
const vtkm::cont::ArrayHandle<T,CVal,DeviceAdapterTag___>& values,
vtkm::cont::ArrayHandle<vtkm::Id,COut,DeviceAdapterTag___>& output);
/// \brief Output is the last index in input for each item in values that wouldn't alter the ordering of input
///
/// LowerBounds is a vectorized search. From each value in \c values it finds
/// the last place the item can be inserted in the ordered \c input array and
/// stores the index in \c output. Uses the custom comparison functor to
/// determine the correct location for each item.
///
/// \par Requirements:
/// \arg \c input must already be sorted
///
template<typename T, class CIn, class CVal, class COut, class Compare>
VTKM_CONT_EXPORT static void UpperBounds(
const vtkm::cont::ArrayHandle<T,CIn,DeviceAdapterTag>& input,
const vtkm::cont::ArrayHandle<T,CVal,DeviceAdapterTag>& values,
vtkm::cont::ArrayHandle<vtkm::Id,COut,DeviceAdapterTag>& output,
Compare comp);
/// \brief A special version of UpperBounds that does an in place operation.
///
/// This version of lower bounds performs an in place operation where each
/// value in the \c values_output array is replaced by the last index in
/// \c input where it occurs. Because this is an in place operation, the type
/// of the arrays is limited to vtkm::Id.
///
template<class CIn, class COut>
VTKM_CONT_EXPORT static void UpperBounds(
const vtkm::cont::ArrayHandle<vtkm::Id,CIn,DeviceAdapterTag___>& input,
vtkm::cont::ArrayHandle<vtkm::Id,COut,DeviceAdapterTag___>& values_output);
};
#else // VTKM_DOXYGEN_ONLY
;
#endif //VTKM_DOXYGEN_ONLY
/// \brief Class providing a device-specific timer.
///
/// The class provide the actual implementation used by vtkm::cont::Timer.
/// A default implementation is provided but device adapters should provide
/// one (in conjunction with DeviceAdapterAlgorithm) where appropriate. The
/// interface for this class is exactly the same as vtkm::cont::Timer.
///
template<class DeviceAdapterTag>
class DeviceAdapterTimerImplementation
{
public:
/// When a timer is constructed, all threads are synchronized and the
/// current time is marked so that GetElapsedTime returns the number of
/// seconds elapsed since the construction.
VTKM_CONT_EXPORT DeviceAdapterTimerImplementation()
{
this->Reset();
}
/// Resets the timer. All further calls to GetElapsedTime will report the
/// number of seconds elapsed since the call to this. This method
/// synchronizes all asynchronous operations.
///
VTKM_CONT_EXPORT void Reset()
{
this->StartTime = this->GetCurrentTime();
}
/// Returns the elapsed time in seconds between the construction of this
/// class or the last call to Reset and the time this function is called. The
/// time returned is measured in wall time. GetElapsedTime may be called any
/// number of times to get the progressive time. This method synchronizes all
/// asynchronous operations.
///
VTKM_CONT_EXPORT vtkm::Scalar GetElapsedTime()
{
TimeStamp currentTime = this->GetCurrentTime();
vtkm::Scalar elapsedTime;
elapsedTime = currentTime.Seconds - this->StartTime.Seconds;
elapsedTime += ((currentTime.Microseconds - this->StartTime.Microseconds)
/vtkm::Scalar(1000000));
return elapsedTime;
}
struct TimeStamp {
vtkm::internal::Int64Type Seconds;
vtkm::internal::Int64Type Microseconds;
};
TimeStamp StartTime;
VTKM_CONT_EXPORT TimeStamp GetCurrentTime()
{
vtkm::cont::DeviceAdapterAlgorithm<DeviceAdapterTag>
::Synchronize();
TimeStamp retval;
#ifdef _WIN32
timeb currentTime;
::ftime(&currentTime);
retval.Seconds = currentTime.time;
retval.Microseconds = 1000*currentTime.millitm;
#else
timeval currentTime;
gettimeofday(&currentTime, NULL);
retval.Seconds = currentTime.tv_sec;
retval.Microseconds = currentTime.tv_usec;
#endif
return retval;
}
};
}
} // namespace vtkm::cont
//-----------------------------------------------------------------------------
// These includes are intentionally placed here after the declaration of the
// DeviceAdapterAlgorithm template prototype, which all the implementations
// need.
#if VTKM_DEVICE_ADAPTER == VTKM_DEVICE_ADAPTER_SERIAL
#include <vtkm/cont/internal/DeviceAdapterAlgorithmSerial.h>
// #elif VTKM_DEVICE_ADAPTER == VTKM_DEVICE_ADAPTER_CUDA
// #include <vtkm/cuda/cont/internal/DeviceAdapterAlgorithmCuda.h>
// #elif VTKM_DEVICE_ADAPTER == VTKM_DEVICE_ADAPTER_OPENMP
// #include <vtkm/openmp/cont/internal/DeviceAdapterAlgorithmOpenMP.h>
// #elif VTKM_DEVICE_ADAPTER == VTKM_DEVICE_ADAPTER_TBB
// #include <vtkm/tbb/cont/internal/DeviceAdapterAlgorithmTBB.h>
#endif
#endif //vtkm_cont_DeviceAdapterAlgorithm_h

@ -0,0 +1,993 @@
//============================================================================
// 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 2014 Sandia Corporation.
// Copyright 2014 UT-Battelle, LLC.
// Copyright 2014. 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 vtkm_cont_internal_DeviceAdapterAlgorithmGeneral_h
#define vtkm_cont_internal_DeviceAdapterAlgorithmGeneral_h
#include <vtkm/cont/ArrayHandle.h>
#include <vtkm/cont/ArrayHandleCounting.h>
#include <vtkm/cont/ArrayContainerControlBasic.h>
#include <vtkm/exec/internal/ErrorMessageBuffer.h>
#include <vtkm/exec/internal/WorkletBase.h>
#include <algorithm>
namespace
{
/// Predicate that takes a single argument \c x, and returns
/// True if it isn't the identity of the Type \p T.
template<typename T>
struct not_default_constructor
{
VTKM_EXEC_CONT_EXPORT bool operator()(const T &x)
{
return (x != T());
}
};
}
namespace vtkm {
namespace cont {
namespace internal {
/// \brief
///
/// This struct provides algorithms that implement "general" device adapter
/// algorithms. If a device adapter provides implementations for Schedule,
/// and Synchronize, the rest of the algorithms can be implemented by calling
/// these functions.
///
/// It should be noted that we recommend that you also implement Sort,
/// ScanInclusive, and ScanExclusive for improved performance.
///
/// An easy way to implement the DeviceAdapterAlgorithm specialization is to
/// subclass this and override the implementation of methods as necessary.
/// As an example, the code would look something like this.
///
/// \code{.cpp}
/// template<>
/// struct DeviceAdapterAlgorithm<DeviceAdapterTagFoo>
/// : DeviceAdapterAlgorithmGeneral<DeviceAdapterAlgorithm<DeviceAdapterTagFoo>,
/// DeviceAdapterTagFoo>
/// {
/// template<class Functor>
/// VTKM_CONT_EXPORT static void Schedule(Functor functor,
/// vtkm::Id numInstances)
/// {
/// ...
/// }
///
/// template<class Functor>
/// VTKM_CONT_EXPORT static void Schedule(Functor functor,
/// vtkm::Id3 maxRange)
/// {
/// ...
/// }
///
/// VTKM_CONT_EXPORT static void Synchronize()
/// {
/// ...
/// }
/// };
/// \endcode
///
/// You might note that DeviceAdapterAlgorithmGeneral has two template
/// parameters that are redundant. Although the first parameter, the class for
/// the actual DeviceAdapterAlgorithm class containing Schedule, and
/// Synchronize is the same as DeviceAdapterAlgorithm<DeviceAdapterTag>, it is
/// made a separate template parameter to avoid a recursive dependence between
/// DeviceAdapterAlgorithmGeneral.h and DeviceAdapterAlgorithm.h
///
template<class DerivedAlgorithm, class DeviceAdapterTag>
struct DeviceAdapterAlgorithmGeneral
{
//--------------------------------------------------------------------------
// Get Execution Value
// This method is used internally to get a single element from the execution
// array. Might want to expose this and/or allow actual device adapter
// implementations to provide one.
private:
template<typename T, class CIn>
VTKM_CONT_EXPORT
static T GetExecutionValue(const vtkm::cont::ArrayHandle<T, CIn> &input,
vtkm::Id index)
{
typedef vtkm::cont::ArrayHandle<T,CIn> InputArrayType;
typedef vtkm::cont::ArrayHandle<T,vtkm::cont::ArrayContainerControlTagBasic>
OutputArrayType;
OutputArrayType output;
CopyKernel<
typename InputArrayType::template ExecutionTypes<DeviceAdapterTag>::PortalConst,
typename OutputArrayType::template ExecutionTypes<DeviceAdapterTag>::Portal>
kernel(input.PrepareForInput(DeviceAdapterTag()),
output.PrepareForOutput(1, DeviceAdapterTag()),
index);
DerivedAlgorithm::Schedule(kernel, 1);
return output.GetPortalConstControl().Get(0);
}
//--------------------------------------------------------------------------
// Copy
private:
template<class InputPortalType, class OutputPortalType>
struct CopyKernel {
InputPortalType InputPortal;
OutputPortalType OutputPortal;
vtkm::Id InputOffset;
vtkm::Id OutputOffset;
VTKM_CONT_EXPORT
CopyKernel(InputPortalType inputPortal,
OutputPortalType outputPortal,
vtkm::Id inputOffset = 0,
vtkm::Id outputOffset = 0)
: InputPortal(inputPortal),
OutputPortal(outputPortal),
InputOffset(inputOffset),
OutputOffset(outputOffset)
{ }
VTKM_EXEC_EXPORT
void operator()(vtkm::Id index) const {
this->OutputPortal.Set(
index + this->OutputOffset,
this->InputPortal.Get(index + this->InputOffset));
}
VTKM_CONT_EXPORT
void SetErrorMessageBuffer(const vtkm::exec::internal::ErrorMessageBuffer &)
{ }
};
public:
template<typename T, class CIn, class COut>
VTKM_CONT_EXPORT static void Copy(const vtkm::cont::ArrayHandle<T, CIn> &input,
vtkm::cont::ArrayHandle<T, COut> &output)
{
vtkm::Id arraySize = input.GetNumberOfValues();
CopyKernel<
typename vtkm::cont::ArrayHandle<T,CIn>::template ExecutionTypes<DeviceAdapterTag>::PortalConst,
typename vtkm::cont::ArrayHandle<T,COut>::template ExecutionTypes<DeviceAdapterTag>::Portal>
kernel(input.PrepareForInput(DeviceAdapterTag()),
output.PrepareForOutput(arraySize, DeviceAdapterTag()));
DerivedAlgorithm::Schedule(kernel, arraySize);
}
//--------------------------------------------------------------------------
// Lower Bounds
private:
template<class InputPortalType,class ValuesPortalType,class OutputPortalType>
struct LowerBoundsKernel {
InputPortalType InputPortal;
ValuesPortalType ValuesPortal;
OutputPortalType OutputPortal;
VTKM_CONT_EXPORT
LowerBoundsKernel(InputPortalType inputPortal,
ValuesPortalType valuesPortal,
OutputPortalType outputPortal)
: InputPortal(inputPortal),
ValuesPortal(valuesPortal),
OutputPortal(outputPortal) { }
VTKM_EXEC_EXPORT
void operator()(vtkm::Id index) const {
// This method assumes that (1) InputPortalType can return working
// iterators in the execution environment and that (2) methods not
// specified with VTKM_EXEC_EXPORT (such as the STL algorithms) can be
// called from the execution environment. Neither one of these is
// necessarily true, but it is true for the current uses of this general
// function and I don't want to compete with STL if I don't have to.
typename InputPortalType::IteratorType resultPos =
std::lower_bound(this->InputPortal.GetIteratorBegin(),
this->InputPortal.GetIteratorEnd(),
this->ValuesPortal.Get(index));
vtkm::Id resultIndex =
static_cast<vtkm::Id>(
std::distance(this->InputPortal.GetIteratorBegin(), resultPos));
this->OutputPortal.Set(index, resultIndex);
}
VTKM_CONT_EXPORT
void SetErrorMessageBuffer(const vtkm::exec::internal::ErrorMessageBuffer &)
{ }
};
template<class InputPortalType,class ValuesPortalType,class OutputPortalType,class Compare>
struct LowerBoundsComparisonKernel {
InputPortalType InputPortal;
ValuesPortalType ValuesPortal;
OutputPortalType OutputPortal;
Compare CompareFunctor;
VTKM_CONT_EXPORT
LowerBoundsComparisonKernel(InputPortalType inputPortal,
ValuesPortalType valuesPortal,
OutputPortalType outputPortal,
Compare comp)
: InputPortal(inputPortal),
ValuesPortal(valuesPortal),
OutputPortal(outputPortal),
CompareFunctor(comp) { }
VTKM_EXEC_EXPORT
void operator()(vtkm::Id index) const {
// This method assumes that (1) InputPortalType can return working
// iterators in the execution environment and that (2) methods not
// specified with VTKM_EXEC_EXPORT (such as the STL algorithms) can be
// called from the execution environment. Neither one of these is
// necessarily true, but it is true for the current uses of this general
// function and I don't want to compete with STL if I don't have to.
typename InputPortalType::IteratorType resultPos =
std::lower_bound(this->InputPortal.GetIteratorBegin(),
this->InputPortal.GetIteratorEnd(),
this->ValuesPortal.Get(index),
this->CompareFunctor);
vtkm::Id resultIndex =
static_cast<vtkm::Id>(
std::distance(this->InputPortal.GetIteratorBegin(), resultPos));
this->OutputPortal.Set(index, resultIndex);
}
VTKM_CONT_EXPORT
void SetErrorMessageBuffer(const vtkm::exec::internal::ErrorMessageBuffer &)
{ }
};
public:
template<typename T, class CIn, class CVal, class COut>
VTKM_CONT_EXPORT static void LowerBounds(
const vtkm::cont::ArrayHandle<T,CIn> &input,
const vtkm::cont::ArrayHandle<T,CVal> &values,
vtkm::cont::ArrayHandle<vtkm::Id,COut> &output)
{
vtkm::Id arraySize = values.GetNumberOfValues();
LowerBoundsKernel<
typename vtkm::cont::ArrayHandle<T,CIn>::template ExecutionTypes<DeviceAdapterTag>::PortalConst,
typename vtkm::cont::ArrayHandle<T,CVal>::template ExecutionTypes<DeviceAdapterTag>::PortalConst,
typename vtkm::cont::ArrayHandle<vtkm::Id,COut>::template ExecutionTypes<DeviceAdapterTag>::Portal>
kernel(input.PrepareForInput(DeviceAdapterTag()),
values.PrepareForInput(DeviceAdapterTag()),
output.PrepareForOutput(arraySize, DeviceAdapterTag()));
DerivedAlgorithm::Schedule(kernel, arraySize);
}
template<typename T, class CIn, class CVal, class COut, class Compare>
VTKM_CONT_EXPORT static void LowerBounds(
const vtkm::cont::ArrayHandle<T,CIn> &input,
const vtkm::cont::ArrayHandle<T,CVal> &values,
vtkm::cont::ArrayHandle<vtkm::Id,COut> &output,
Compare comp)
{
vtkm::Id arraySize = values.GetNumberOfValues();
LowerBoundsComparisonKernel<
typename vtkm::cont::ArrayHandle<T,CIn>::template ExecutionTypes<DeviceAdapterTag>::PortalConst,
typename vtkm::cont::ArrayHandle<T,CVal>::template ExecutionTypes<DeviceAdapterTag>::PortalConst,
typename vtkm::cont::ArrayHandle<vtkm::Id,COut>::template ExecutionTypes<DeviceAdapterTag>::Portal,
Compare>
kernel(input.PrepareForInput(DeviceAdapterTag()),
values.PrepareForInput(DeviceAdapterTag()),
output.PrepareForOutput(arraySize, DeviceAdapterTag()),
comp);
DerivedAlgorithm::Schedule(kernel, arraySize);
}
template<class CIn, class COut>
VTKM_CONT_EXPORT static void LowerBounds(
const vtkm::cont::ArrayHandle<vtkm::Id,CIn> &input,
vtkm::cont::ArrayHandle<vtkm::Id,COut> &values_output)
{
DeviceAdapterAlgorithmGeneral<
DerivedAlgorithm,DeviceAdapterTag>::LowerBounds(input,
values_output,
values_output);
}
//--------------------------------------------------------------------------
// Scan Exclusive
private:
template<typename PortalType>
struct SetConstantKernel
{
typedef typename PortalType::ValueType ValueType;
PortalType Portal;
ValueType Value;
VTKM_CONT_EXPORT
SetConstantKernel(const PortalType &portal, ValueType value)
: Portal(portal), Value(value) { }
VTKM_EXEC_EXPORT
void operator()(vtkm::Id index) const
{
this->Portal.Set(index, this->Value);
}
VTKM_CONT_EXPORT
void SetErrorMessageBuffer(const vtkm::exec::internal::ErrorMessageBuffer &)
{ }
};
public:
template<typename T, class CIn, class COut>
VTKM_CONT_EXPORT static T ScanExclusive(
const vtkm::cont::ArrayHandle<T,CIn> &input,
vtkm::cont::ArrayHandle<T,COut>& output)
{
typedef vtkm::cont::ArrayHandle<T,vtkm::cont::ArrayContainerControlTagBasic>
TempArrayType;
typedef vtkm::cont::ArrayHandle<T,COut> OutputArrayType;
TempArrayType inclusiveScan;
T result = DerivedAlgorithm::ScanInclusive(input, inclusiveScan);
vtkm::Id numValues = inclusiveScan.GetNumberOfValues();
if (numValues < 1)
{
return result;
}
typedef typename TempArrayType::template ExecutionTypes<DeviceAdapterTag>
::PortalConst SrcPortalType;
SrcPortalType srcPortal = inclusiveScan.PrepareForInput(DeviceAdapterTag());
typedef typename OutputArrayType::template ExecutionTypes<DeviceAdapterTag>
::Portal DestPortalType;
DestPortalType destPortal = output.PrepareForOutput(numValues,
DeviceAdapterTag());
// Set first value in output (always 0).
DerivedAlgorithm::Schedule(
SetConstantKernel<DestPortalType>(destPortal,0), 1);
// Shift remaining values over by one.
DerivedAlgorithm::Schedule(
CopyKernel<SrcPortalType,DestPortalType>(srcPortal,
destPortal,
0,
1),
numValues - 1);
return result;
}
//--------------------------------------------------------------------------
// Scan Inclusive
private:
template<typename PortalType>
struct ScanKernel : vtkm::exec::internal::WorkletBase
{
PortalType Portal;
vtkm::Id Stride;
vtkm::Id Offset;
vtkm::Id Distance;
VTKM_CONT_EXPORT
ScanKernel(const PortalType &portal, vtkm::Id stride, vtkm::Id offset)
: Portal(portal),
Stride(stride),
Offset(offset),
Distance(stride/2)
{ }
VTKM_EXEC_EXPORT
void operator()(vtkm::Id index) const
{
typedef typename PortalType::ValueType ValueType;
vtkm::Id leftIndex = this->Offset + index*this->Stride;
vtkm::Id rightIndex = leftIndex + this->Distance;
if (rightIndex < this->Portal.GetNumberOfValues())
{
ValueType leftValue = this->Portal.Get(leftIndex);
ValueType rightValue = this->Portal.Get(rightIndex);
this->Portal.Set(rightIndex, leftValue+rightValue);
}
}
};
public:
template<typename T, class CIn, class COut>
VTKM_CONT_EXPORT static T ScanInclusive(
const vtkm::cont::ArrayHandle<T,CIn> &input,
vtkm::cont::ArrayHandle<T,COut>& output)
{
typedef typename
vtkm::cont::ArrayHandle<T,COut>
::template ExecutionTypes<DeviceAdapterTag>::Portal PortalType;
DerivedAlgorithm::Copy(input, output);
vtkm::Id numValues = output.GetNumberOfValues();
if (numValues < 1)
{
return 0;
}
PortalType portal = output.PrepareForInPlace(DeviceAdapterTag());
vtkm::Id stride;
for (stride = 2; stride-1 < numValues; stride *= 2)
{
ScanKernel<PortalType> kernel(portal, stride, stride/2 - 1);
DerivedAlgorithm::Schedule(kernel, numValues/stride);
}
// Do reverse operation on odd indices. Start at stride we were just at.
for (stride /= 2; stride > 1; stride /= 2)
{
ScanKernel<PortalType> kernel(portal, stride, stride - 1);
DerivedAlgorithm::Schedule(kernel, numValues/stride);
}
return GetExecutionValue(output, numValues-1);
}
//--------------------------------------------------------------------------
// Sort
private:
template<typename PortalType, typename CompareType>
struct BitonicSortMergeKernel : vtkm::exec::internal::WorkletBase
{
PortalType Portal;
CompareType Compare;
vtkm::Id GroupSize;
VTKM_CONT_EXPORT
BitonicSortMergeKernel(const PortalType &portal,
const CompareType &compare,
vtkm::Id groupSize)
: Portal(portal), Compare(compare), GroupSize(groupSize) { }
VTKM_EXEC_EXPORT
void operator()(vtkm::Id index) const {
typedef typename PortalType::ValueType ValueType;
vtkm::Id groupIndex = index%this->GroupSize;
vtkm::Id blockSize = 2*this->GroupSize;
vtkm::Id blockIndex = index/this->GroupSize;
vtkm::Id lowIndex = blockIndex * blockSize + groupIndex;
vtkm::Id highIndex = lowIndex + this->GroupSize;
if (highIndex < this->Portal.GetNumberOfValues())
{
ValueType lowValue = this->Portal.Get(lowIndex);
ValueType highValue = this->Portal.Get(highIndex);
if (this->Compare(highValue, lowValue))
{
this->Portal.Set(highIndex, lowValue);
this->Portal.Set(lowIndex, highValue);
}
}
}
};
template<typename PortalType, typename CompareType>
struct BitonicSortCrossoverKernel : vtkm::exec::internal::WorkletBase
{
PortalType Portal;
CompareType Compare;
vtkm::Id GroupSize;
VTKM_CONT_EXPORT
BitonicSortCrossoverKernel(const PortalType &portal,
const CompareType &compare,
vtkm::Id groupSize)
: Portal(portal), Compare(compare), GroupSize(groupSize) { }
VTKM_EXEC_EXPORT
void operator()(vtkm::Id index) const {
typedef typename PortalType::ValueType ValueType;
vtkm::Id groupIndex = index%this->GroupSize;
vtkm::Id blockSize = 2*this->GroupSize;
vtkm::Id blockIndex = index/this->GroupSize;
vtkm::Id lowIndex = blockIndex*blockSize + groupIndex;
vtkm::Id highIndex = blockIndex*blockSize + (blockSize - groupIndex - 1);
if (highIndex < this->Portal.GetNumberOfValues())
{
ValueType lowValue = this->Portal.Get(lowIndex);
ValueType highValue = this->Portal.Get(highIndex);
if (this->Compare(highValue, lowValue))
{
this->Portal.Set(highIndex, lowValue);
this->Portal.Set(lowIndex, highValue);
}
}
}
};
struct DefaultCompareFunctor
{
template<typename T>
VTKM_EXEC_EXPORT
bool operator()(const T& first, const T& second) const
{
return first < second;
}
};
public:
template<typename T, class Container, class CompareType>
VTKM_CONT_EXPORT static void Sort(
vtkm::cont::ArrayHandle<T,Container> &values,
CompareType compare)
{
typedef typename vtkm::cont::ArrayHandle<T,Container> ArrayType;
typedef typename ArrayType::template ExecutionTypes<DeviceAdapterTag>
::Portal PortalType;
vtkm::Id numValues = values.GetNumberOfValues();
if (numValues < 2) { return; }
PortalType portal = values.PrepareForInPlace(DeviceAdapterTag());
vtkm::Id numThreads = 1;
while (numThreads < numValues) { numThreads *= 2; }
numThreads /= 2;
typedef BitonicSortMergeKernel<PortalType,CompareType> MergeKernel;
typedef BitonicSortCrossoverKernel<PortalType,CompareType> CrossoverKernel;
for (vtkm::Id crossoverSize = 1;
crossoverSize < numValues;
crossoverSize *= 2)
{
DerivedAlgorithm::Schedule(CrossoverKernel(portal,compare,crossoverSize),
numThreads);
for (vtkm::Id mergeSize = crossoverSize/2; mergeSize > 0; mergeSize /= 2)
{
DerivedAlgorithm::Schedule(MergeKernel(portal,compare,mergeSize),
numThreads);
}
}
}
template<typename T, class Container>
VTKM_CONT_EXPORT static void Sort(
vtkm::cont::ArrayHandle<T,Container> &values)
{
DerivedAlgorithm::Sort(values, DefaultCompareFunctor());
}
//--------------------------------------------------------------------------
// Stream Compact
private:
template<class StencilPortalType, class OutputPortalType>
struct StencilToIndexFlagKernel
{
typedef typename StencilPortalType::ValueType StencilValueType;
StencilPortalType StencilPortal;
OutputPortalType OutputPortal;
VTKM_CONT_EXPORT
StencilToIndexFlagKernel(StencilPortalType stencilPortal,
OutputPortalType outputPortal)
: StencilPortal(stencilPortal), OutputPortal(outputPortal) { }
VTKM_EXEC_EXPORT
void operator()(vtkm::Id index) const
{
StencilValueType value = this->StencilPortal.Get(index);
bool flag = not_default_constructor<StencilValueType>()(value);
this->OutputPortal.Set(index, flag ? 1 : 0);
}
VTKM_CONT_EXPORT
void SetErrorMessageBuffer(const vtkm::exec::internal::ErrorMessageBuffer &)
{ }
};
template<class InputPortalType,
class StencilPortalType,
class IndexPortalType,
class OutputPortalType>
struct CopyIfKernel
{
InputPortalType InputPortal;
StencilPortalType StencilPortal;
IndexPortalType IndexPortal;
OutputPortalType OutputPortal;
VTKM_CONT_EXPORT
CopyIfKernel(InputPortalType inputPortal,
StencilPortalType stencilPortal,
IndexPortalType indexPortal,
OutputPortalType outputPortal)
: InputPortal(inputPortal),
StencilPortal(stencilPortal),
IndexPortal(indexPortal),
OutputPortal(outputPortal) { }
VTKM_EXEC_EXPORT
void operator()(vtkm::Id index) const
{
typedef typename StencilPortalType::ValueType StencilValueType;
StencilValueType stencilValue = this->StencilPortal.Get(index);
if (not_default_constructor<StencilValueType>()(stencilValue))
{
vtkm::Id outputIndex = this->IndexPortal.Get(index);
typedef typename OutputPortalType::ValueType OutputValueType;
OutputValueType value = this->InputPortal.Get(index);
this->OutputPortal.Set(outputIndex, value);
}
}
VTKM_CONT_EXPORT
void SetErrorMessageBuffer(const vtkm::exec::internal::ErrorMessageBuffer &)
{ }
};
public:
template<typename T, typename U, class CIn, class CStencil, class COut>
VTKM_CONT_EXPORT static void StreamCompact(
const vtkm::cont::ArrayHandle<T,CIn>& input,
const vtkm::cont::ArrayHandle<U,CStencil>& stencil,
vtkm::cont::ArrayHandle<T,COut>& output)
{
VTKM_ASSERT_CONT(input.GetNumberOfValues() == stencil.GetNumberOfValues());
vtkm::Id arrayLength = stencil.GetNumberOfValues();
typedef vtkm::cont::ArrayHandle<
vtkm::Id, vtkm::cont::ArrayContainerControlTagBasic> IndexArrayType;
IndexArrayType indices;
typedef typename vtkm::cont::ArrayHandle<U,CStencil>
::template ExecutionTypes<DeviceAdapterTag>::PortalConst
StencilPortalType;
StencilPortalType stencilPortal =
stencil.PrepareForInput(DeviceAdapterTag());
typedef typename IndexArrayType
::template ExecutionTypes<DeviceAdapterTag>::Portal IndexPortalType;
IndexPortalType indexPortal =
indices.PrepareForOutput(arrayLength, DeviceAdapterTag());
StencilToIndexFlagKernel<
StencilPortalType, IndexPortalType> indexKernel(stencilPortal,
indexPortal);
DerivedAlgorithm::Schedule(indexKernel, arrayLength);
vtkm::Id outArrayLength = DerivedAlgorithm::ScanExclusive(indices, indices);
typedef typename vtkm::cont::ArrayHandle<T,CIn>
::template ExecutionTypes<DeviceAdapterTag>::PortalConst
InputPortalType;
InputPortalType inputPortal = input.PrepareForInput(DeviceAdapterTag());
typedef typename vtkm::cont::ArrayHandle<T,COut>
::template ExecutionTypes<DeviceAdapterTag>::Portal OutputPortalType;
OutputPortalType outputPortal =
output.PrepareForOutput(outArrayLength, DeviceAdapterTag());
CopyIfKernel<
InputPortalType,
StencilPortalType,
IndexPortalType,
OutputPortalType>copyKernel(inputPortal,
stencilPortal,
indexPortal,
outputPortal);
DerivedAlgorithm::Schedule(copyKernel, arrayLength);
}
template<typename T, class CStencil, class COut>
VTKM_CONT_EXPORT static void StreamCompact(
const vtkm::cont::ArrayHandle<T,CStencil> &stencil,
vtkm::cont::ArrayHandle<vtkm::Id,COut> &output)
{
typedef vtkm::cont::ArrayHandleCounting<vtkm::Id> CountingHandleType;
CountingHandleType input =
vtkm::cont::make_ArrayHandleCounting(vtkm::Id(0),
stencil.GetNumberOfValues());
DerivedAlgorithm::StreamCompact(input, stencil, output);
}
//--------------------------------------------------------------------------
// Unique
private:
template<class InputPortalType, class StencilPortalType>
struct ClassifyUniqueKernel {
InputPortalType InputPortal;
StencilPortalType StencilPortal;
VTKM_CONT_EXPORT
ClassifyUniqueKernel(InputPortalType inputPortal,
StencilPortalType stencilPortal)
: InputPortal(inputPortal), StencilPortal(stencilPortal) { }
VTKM_EXEC_EXPORT
void operator()(vtkm::Id index) const {
typedef typename StencilPortalType::ValueType ValueType;
if (index == 0)
{
// Always copy first value.
this->StencilPortal.Set(index, ValueType(1));
}
else
{
ValueType flag = ValueType(this->InputPortal.Get(index-1)
!= this->InputPortal.Get(index));
this->StencilPortal.Set(index, flag);
}
}
VTKM_CONT_EXPORT
void SetErrorMessageBuffer(const vtkm::exec::internal::ErrorMessageBuffer &)
{ }
};
template<class InputPortalType, class StencilPortalType, class Compare>
struct ClassifyUniqueComparisonKernel {
InputPortalType InputPortal;
StencilPortalType StencilPortal;
Compare CompareFunctor;
VTKM_CONT_EXPORT
ClassifyUniqueComparisonKernel(InputPortalType inputPortal,
StencilPortalType stencilPortal,
Compare comp):
InputPortal(inputPortal),
StencilPortal(stencilPortal),
CompareFunctor(comp) { }
VTKM_EXEC_EXPORT
void operator()(vtkm::Id index) const {
typedef typename StencilPortalType::ValueType ValueType;
if (index == 0)
{
// Always copy first value.
this->StencilPortal.Set(index, ValueType(1));
}
else
{
//comparison predicate returns true when they match
const bool same = !(this->CompareFunctor(this->InputPortal.Get(index-1),
this->InputPortal.Get(index)));
ValueType flag = ValueType(same);
this->StencilPortal.Set(index, flag);
}
}
VTKM_CONT_EXPORT
void SetErrorMessageBuffer(const vtkm::exec::internal::ErrorMessageBuffer &)
{ }
};
public:
template<typename T, class Container>
VTKM_CONT_EXPORT static void Unique(
vtkm::cont::ArrayHandle<T,Container> &values)
{
vtkm::cont::ArrayHandle<vtkm::Id, vtkm::cont::ArrayContainerControlTagBasic>
stencilArray;
vtkm::Id inputSize = values.GetNumberOfValues();
ClassifyUniqueKernel<
typename vtkm::cont::ArrayHandle<T,Container>::template ExecutionTypes<DeviceAdapterTag>::PortalConst,
typename vtkm::cont::ArrayHandle<vtkm::Id,vtkm::cont::ArrayContainerControlTagBasic>::template ExecutionTypes<DeviceAdapterTag>::Portal>
classifyKernel(values.PrepareForInput(DeviceAdapterTag()),
stencilArray.PrepareForOutput(inputSize, DeviceAdapterTag()));
DerivedAlgorithm::Schedule(classifyKernel, inputSize);
vtkm::cont::ArrayHandle<T, vtkm::cont::ArrayContainerControlTagBasic>
outputArray;
DerivedAlgorithm::StreamCompact(values, stencilArray, outputArray);
DerivedAlgorithm::Copy(outputArray, values);
}
template<typename T, class Container, class Compare>
VTKM_CONT_EXPORT static void Unique(
vtkm::cont::ArrayHandle<T,Container> &values,
Compare comp)
{
vtkm::cont::ArrayHandle<vtkm::Id, vtkm::cont::ArrayContainerControlTagBasic>
stencilArray;
vtkm::Id inputSize = values.GetNumberOfValues();
ClassifyUniqueComparisonKernel<
typename vtkm::cont::ArrayHandle<T,Container>::template ExecutionTypes<DeviceAdapterTag>::PortalConst,
typename vtkm::cont::ArrayHandle<vtkm::Id,vtkm::cont::ArrayContainerControlTagBasic>::template ExecutionTypes<DeviceAdapterTag>::Portal,
Compare>
classifyKernel(values.PrepareForInput(DeviceAdapterTag()),
stencilArray.PrepareForOutput(inputSize, DeviceAdapterTag()),
comp);
DerivedAlgorithm::Schedule(classifyKernel, inputSize);
vtkm::cont::ArrayHandle<T, vtkm::cont::ArrayContainerControlTagBasic>
outputArray;
DerivedAlgorithm::StreamCompact(values, stencilArray, outputArray);
DerivedAlgorithm::Copy(outputArray, values);
}
//--------------------------------------------------------------------------
// Upper bounds
private:
template<class InputPortalType,class ValuesPortalType,class OutputPortalType>
struct UpperBoundsKernel {
InputPortalType InputPortal;
ValuesPortalType ValuesPortal;
OutputPortalType OutputPortal;
VTKM_CONT_EXPORT
UpperBoundsKernel(InputPortalType inputPortal,
ValuesPortalType valuesPortal,
OutputPortalType outputPortal)
: InputPortal(inputPortal),
ValuesPortal(valuesPortal),
OutputPortal(outputPortal) { }
VTKM_EXEC_EXPORT
void operator()(vtkm::Id index) const {
// This method assumes that (1) InputPortalType can return working
// iterators in the execution environment and that (2) methods not
// specified with VTKM_EXEC_EXPORT (such as the STL algorithms) can be
// called from the execution environment. Neither one of these is
// necessarily true, but it is true for the current uses of this general
// function and I don't want to compete with STL if I don't have to.
typename InputPortalType::IteratorType resultPos =
std::upper_bound(this->InputPortal.GetIteratorBegin(),
this->InputPortal.GetIteratorEnd(),
this->ValuesPortal.Get(index));
vtkm::Id resultIndex =
static_cast<vtkm::Id>(
std::distance(this->InputPortal.GetIteratorBegin(), resultPos));
this->OutputPortal.Set(index, resultIndex);
}
VTKM_CONT_EXPORT
void SetErrorMessageBuffer(const vtkm::exec::internal::ErrorMessageBuffer &)
{ }
};
template<class InputPortalType,class ValuesPortalType,class OutputPortalType,class Compare>
struct UpperBoundsKernelComparisonKernel {
InputPortalType InputPortal;
ValuesPortalType ValuesPortal;
OutputPortalType OutputPortal;
Compare CompareFunctor;
VTKM_CONT_EXPORT
UpperBoundsKernelComparisonKernel(InputPortalType inputPortal,
ValuesPortalType valuesPortal,
OutputPortalType outputPortal,
Compare comp)
: InputPortal(inputPortal),
ValuesPortal(valuesPortal),
OutputPortal(outputPortal),
CompareFunctor(comp) { }
VTKM_EXEC_EXPORT
void operator()(vtkm::Id index) const {
// This method assumes that (1) InputPortalType can return working
// iterators in the execution environment and that (2) methods not
// specified with VTKM_EXEC_EXPORT (such as the STL algorithms) can be
// called from the execution environment. Neither one of these is
// necessarily true, but it is true for the current uses of this general
// function and I don't want to compete with STL if I don't have to.
typename InputPortalType::IteratorType resultPos =
std::upper_bound(this->InputPortal.GetIteratorBegin(),
this->InputPortal.GetIteratorEnd(),
this->ValuesPortal.Get(index),
this->CompareFunctor);
vtkm::Id resultIndex =
static_cast<vtkm::Id>(
std::distance(this->InputPortal.GetIteratorBegin(), resultPos));
this->OutputPortal.Set(index, resultIndex);
}
VTKM_CONT_EXPORT
void SetErrorMessageBuffer(const vtkm::exec::internal::ErrorMessageBuffer &)
{ }
};
public:
template<typename T, class CIn, class CVal, class COut>
VTKM_CONT_EXPORT static void UpperBounds(
const vtkm::cont::ArrayHandle<T,CIn> &input,
const vtkm::cont::ArrayHandle<T,CVal> &values,
vtkm::cont::ArrayHandle<vtkm::Id,COut> &output)
{
vtkm::Id arraySize = values.GetNumberOfValues();
UpperBoundsKernel<
typename vtkm::cont::ArrayHandle<T,CIn>::template ExecutionTypes<DeviceAdapterTag>::PortalConst,
typename vtkm::cont::ArrayHandle<T,CVal>::template ExecutionTypes<DeviceAdapterTag>::PortalConst,
typename vtkm::cont::ArrayHandle<T,COut>::template ExecutionTypes<DeviceAdapterTag>::Portal>
kernel(input.PrepareForInput(DeviceAdapterTag()),
values.PrepareForInput(DeviceAdapterTag()),
output.PrepareForOutput(arraySize, DeviceAdapterTag()));
DerivedAlgorithm::Schedule(kernel, arraySize);
}
template<typename T, class CIn, class CVal, class COut, class Compare>
VTKM_CONT_EXPORT static void UpperBounds(
const vtkm::cont::ArrayHandle<T,CIn> &input,
const vtkm::cont::ArrayHandle<T,CVal> &values,
vtkm::cont::ArrayHandle<vtkm::Id,COut> &output,
Compare comp)
{
vtkm::Id arraySize = values.GetNumberOfValues();
UpperBoundsKernelComparisonKernel<
typename vtkm::cont::ArrayHandle<T,CIn>::template ExecutionTypes<DeviceAdapterTag>::PortalConst,
typename vtkm::cont::ArrayHandle<T,CVal>::template ExecutionTypes<DeviceAdapterTag>::PortalConst,
typename vtkm::cont::ArrayHandle<T,COut>::template ExecutionTypes<DeviceAdapterTag>::Portal,
Compare>
kernel(input.PrepareForInput(DeviceAdapterTag()),
values.PrepareForInput(DeviceAdapterTag()),
output.PrepareForOutput(arraySize, DeviceAdapterTag()),
comp);
DerivedAlgorithm::Schedule(kernel, arraySize);
}
template<class CIn, class COut>
VTKM_CONT_EXPORT static void UpperBounds(
const vtkm::cont::ArrayHandle<vtkm::Id,CIn> &input,
vtkm::cont::ArrayHandle<vtkm::Id,COut> &values_output)
{
DeviceAdapterAlgorithmGeneral<DerivedAlgorithm,
DeviceAdapterTag>::UpperBounds(input, values_output, values_output);
}
};
}
}
} // namespace vtkm::cont::internal
#endif //vtkm_cont_internal_DeviceAdapterAlgorithmGeneral_h

@ -0,0 +1,190 @@
//============================================================================
// 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 2014 Sandia Corporation.
// Copyright 2014 UT-Battelle, LLC.
// Copyright 2014. 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 vtkm_cont_internal_DeviceAdapterAlgorithmSerial_h
#define vtkm_cont_internal_DeviceAdapterAlgorithmSerial_h
#include <vtkm/cont/ArrayHandle.h>
#include <vtkm/cont/ErrorExecution.h>
#include <vtkm/cont/internal/DeviceAdapterAlgorithm.h>
#include <vtkm/cont/internal/DeviceAdapterAlgorithmGeneral.h>
#include <vtkm/cont/internal/DeviceAdapterTagSerial.h>
#include <vtkm/exec/internal/ErrorMessageBuffer.h>
#include <boost/iterator/counting_iterator.hpp>
#include <boost/utility/enable_if.hpp>
#include <algorithm>
#include <numeric>
namespace vtkm {
namespace cont {
template<>
struct DeviceAdapterAlgorithm<vtkm::cont::DeviceAdapterTagSerial> :
vtkm::cont::internal::DeviceAdapterAlgorithmGeneral<
DeviceAdapterAlgorithm<vtkm::cont::DeviceAdapterTagSerial>,
vtkm::cont::DeviceAdapterTagSerial>
{
private:
typedef vtkm::cont::DeviceAdapterTagSerial Device;
public:
template<typename T, class CIn, class COut>
VTKM_CONT_EXPORT static T ScanInclusive(
const vtkm::cont::ArrayHandle<T,CIn> &input,
vtkm::cont::ArrayHandle<T,COut>& output)
{
typedef typename vtkm::cont::ArrayHandle<T,COut>
::template ExecutionTypes<Device>::Portal PortalOut;
typedef typename vtkm::cont::ArrayHandle<T,CIn>
::template ExecutionTypes<Device>::PortalConst PortalIn;
vtkm::Id numberOfValues = input.GetNumberOfValues();
PortalIn inputPortal = input.PrepareForInput(Device());
PortalOut outputPortal = output.PrepareForOutput(numberOfValues, Device());
if (numberOfValues <= 0) { return 0; }
std::partial_sum(inputPortal.GetIteratorBegin(),
inputPortal.GetIteratorEnd(),
outputPortal.GetIteratorBegin());
// Return the value at the last index in the array, which is the full sum.
return outputPortal.Get(numberOfValues - 1);
}
template<typename T, class CIn, class COut>
VTKM_CONT_EXPORT static T ScanExclusive(
const vtkm::cont::ArrayHandle<T,CIn> &input,
vtkm::cont::ArrayHandle<T,COut>& output)
{
typedef typename vtkm::cont::ArrayHandle<T,COut>
::template ExecutionTypes<Device>::Portal PortalOut;
typedef typename vtkm::cont::ArrayHandle<T,CIn>
::template ExecutionTypes<Device>::PortalConst PortalIn;
vtkm::Id numberOfValues = input.GetNumberOfValues();
PortalIn inputPortal = input.PrepareForInput(Device());
PortalOut outputPortal = output.PrepareForOutput(numberOfValues, Device());
if (numberOfValues <= 0) { return 0; }
std::partial_sum(inputPortal.GetIteratorBegin(),
inputPortal.GetIteratorEnd(),
outputPortal.GetIteratorBegin());
T fullSum = outputPortal.Get(numberOfValues - 1);
// Shift right by one
std::copy_backward(outputPortal.GetIteratorBegin(),
outputPortal.GetIteratorEnd()-1,
outputPortal.GetIteratorEnd());
outputPortal.Set(0, 0);
return fullSum;
}
private:
// This runs in the execution environment.
template<class FunctorType>
class ScheduleKernel
{
public:
ScheduleKernel(const FunctorType &functor)
: Functor(functor) { }
//needed for when calling from schedule on a range
VTKM_EXEC_EXPORT void operator()(vtkm::Id index) const
{
this->Functor(index);
}
private:
const FunctorType Functor;
};
public:
template<class Functor>
VTKM_CONT_EXPORT static void Schedule(Functor functor,
vtkm::Id numInstances)
{
const vtkm::Id MESSAGE_SIZE = 1024;
char errorString[MESSAGE_SIZE];
errorString[0] = '\0';
vtkm::exec::internal::ErrorMessageBuffer
errorMessage(errorString, MESSAGE_SIZE);
functor.SetErrorMessageBuffer(errorMessage);
DeviceAdapterAlgorithm<Device>::ScheduleKernel<Functor> kernel(functor);
std::for_each(
::boost::counting_iterator<vtkm::Id>(0),
::boost::counting_iterator<vtkm::Id>(numInstances),
kernel);
if (errorMessage.IsErrorRaised())
{
throw vtkm::cont::ErrorExecution(errorString);
}
}
template<class FunctorType>
VTKM_CONT_EXPORT
static void Schedule(FunctorType functor, vtkm::Id3 rangeMax)
{
DeviceAdapterAlgorithm<Device>::Schedule(functor,
rangeMax[0] * rangeMax[1] * rangeMax[2] );
}
template<typename T, class Container>
VTKM_CONT_EXPORT static void Sort(vtkm::cont::ArrayHandle<T,Container>& values)
{
typedef typename vtkm::cont::ArrayHandle<T,Container>
::template ExecutionTypes<Device>::Portal PortalType;
PortalType arrayPortal = values.PrepareForInPlace(Device());
std::sort(arrayPortal.GetIteratorBegin(), arrayPortal.GetIteratorEnd());
}
template<typename T, class Container, class Compare>
VTKM_CONT_EXPORT static void Sort(vtkm::cont::ArrayHandle<T,Container>& values,
Compare comp)
{
typedef typename vtkm::cont::ArrayHandle<T,Container>
::template ExecutionTypes<Device>::Portal PortalType;
PortalType arrayPortal = values.PrepareForInPlace(Device());
std::sort(arrayPortal.GetIteratorBegin(), arrayPortal.GetIteratorEnd(),comp);
}
VTKM_CONT_EXPORT static void Synchronize()
{
// Nothing to do. This device is serial and has no asynchronous operations.
}
};
}
} // namespace vtkm::cont
#endif //vtkm_cont_internal_DeviceAdapterAlgorithmSerial_h

@ -0,0 +1,32 @@
//============================================================================
// 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 2014 Sandia Corporation.
// Copyright 2014 UT-Battelle, LLC.
// Copyright 2014. 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 vtkm_cont_internal_DeviceAdapterError_h
#define vtkm_cont_internal_DeviceAdapterError_h
#include <vtkm/cont/internal/DeviceAdapterTag.h>
/// This is an invalid DeviceAdapter. The point of this class is to include the
/// header file to make this invalid class the default DeviceAdapter. From that
/// point, you have to specify an appropriate DeviceAdapter or else get a
/// compile error.
///
VTKM_CREATE_DEVICE_ADAPTER(Error);
#endif //vtkm_cont_internal_DeviceAdapterError_h

@ -91,6 +91,11 @@ struct DeviceAdapterTagCheck
#include <vtkm/cont/internal/DeviceAdapterTagSerial.h>
#define VTKM_DEFAULT_DEVICE_ADAPTER_TAG ::vtkm::cont::DeviceAdapterTagSerial
#elif VTKM_DEVICE_ADAPTER == VTKM_DEVICE_ADAPTER_ERROR
#include <vtkm/cont/internal/DeviceAdapterError.h>
#define VTKM_DEFAULT_DEVICE_ADAPTER_TAG ::vtkm::cont::DeviceAdapterTagError
#elif (VTKM_DEVICE_ADAPTER == VTKM_DEVICE_ADAPTER_UNDEFINED) || !defined(VTKM_DEVICE_ADAPTER)
#ifndef VTKM_DEFAULT_DEVICE_ADAPTER_TAG

@ -22,6 +22,6 @@
set(unit_tests
UnitTestArrayManagerExecutionShareWithControl.cxx
UnitTestArrayPortalFromIterators.cxx
# UnitTestIteratorFromArrayPortal.cxx
UnitTestIteratorFromArrayPortal.cxx
)
vtkm_unit_tests(SOURCES ${unit_tests})

@ -20,6 +20,7 @@
set(headers
Testing.h
TestingDeviceAdapter.h
)
vtkm_declare_headers(${headers})
@ -28,7 +29,11 @@ set(unit_tests
UnitTestArrayContainerControlBasic.cxx
UnitTestArrayContainerControlImplicit.cxx
UnitTestArrayHandle.cxx
UnitTestArrayHandleCounting.cxx
UnitTestContTesting.cxx
UnitTestDeviceAdapterAlgorithmDependency.cxx
UnitTestDeviceAdapterAlgorithmGeneral.cxx
UnitTestDeviceAdapterSerial.cxx
)
vtkm_unit_tests(SOURCES ${unit_tests})

File diff suppressed because it is too large Load Diff

@ -0,0 +1,125 @@
//============================================================================
// 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 2014 Sandia Corporation.
// Copyright 2014 UT-Battelle, LLC.
// Copyright 2014. 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.
//============================================================================
#define VTKM_DEVICE_ADAPTER VTKM_DEVICE_ADAPTER_SERIAL
#include <vtkm/cont/ArrayHandleCounting.h>
#include <vtkm/cont/testing/Testing.h>
namespace {
const vtkm::Id ARRAY_SIZE = 10;
//increments by two instead of one wrapper
template<typename T>
struct CountByTwo
{
CountByTwo(): Value() {}
explicit CountByTwo(T t): Value(t) {}
bool operator==(const T& other) const
{ return Value == other; }
bool operator==(const CountByTwo<T>& other) const
{ return Value == other.Value; }
CountByTwo<T> operator+(vtkm::Id count) const
{ return CountByTwo<T>(Value+(count*2)); }
CountByTwo<T>& operator++()
{ ++Value; ++Value; return *this; }
friend std::ostream& operator<< (std::ostream& os, const CountByTwo<T>& obj)
{ os << obj.Value; return os; }
T Value;
};
template< typename ValueType>
struct TemplatedTests
{
typedef vtkm::cont::ArrayHandleCounting<ValueType> ArrayHandleType;
typedef vtkm::cont::ArrayHandle<ValueType,
typename vtkm::cont::internal::ArrayHandleCountingTraits<ValueType>::Tag>
ArrayHandleType2;
typedef typename ArrayHandleType::PortalConstControl PortalType;
void operator()( const ValueType startingValue )
{
ArrayHandleType arrayConst(startingValue, ARRAY_SIZE);
ArrayHandleType arrayMake = vtkm::cont::make_ArrayHandleCounting(startingValue,ARRAY_SIZE);
ArrayHandleType2 arrayHandle =
ArrayHandleType2(PortalType(startingValue, ARRAY_SIZE));
VTKM_TEST_ASSERT(arrayConst.GetNumberOfValues() == ARRAY_SIZE,
"Counting array using constructor has wrong size.");
VTKM_TEST_ASSERT(arrayMake.GetNumberOfValues() == ARRAY_SIZE,
"Counting array using make has wrong size.");
VTKM_TEST_ASSERT(arrayHandle.GetNumberOfValues() == ARRAY_SIZE,
"Counting array using raw array handle + tag has wrong size.");
ValueType properValue = startingValue;
for (vtkm::Id index = 0; index < ARRAY_SIZE; index++)
{
VTKM_TEST_ASSERT(arrayConst.GetPortalConstControl().Get(index) == properValue,
"Counting array using constructor has unexpected value.");
VTKM_TEST_ASSERT(arrayMake.GetPortalConstControl().Get(index) == properValue,
"Counting array using make has unexpected value.");
VTKM_TEST_ASSERT(arrayHandle.GetPortalConstControl().Get(index) == properValue,
"Counting array using raw array handle + tag has unexpected value.");
++properValue;
}
}
};
struct TestFunctor
{
template <typename T>
void operator()(const T t)
{
TemplatedTests<T> tests;
tests(t);
}
};
void TestArrayHandleCounting()
{
TestFunctor()(vtkm::Id(0));
TestFunctor()(vtkm::Scalar(0));
TestFunctor()( CountByTwo<vtkm::Id>(12) );
TestFunctor()( CountByTwo<vtkm::Scalar>(1.2f) );
}
} // annonymous namespace
int UnitTestArrayHandleCounting(int, char *[])
{
return vtkm::cont::testing::Testing::Run(TestArrayHandleCounting);
}

@ -0,0 +1,57 @@
//============================================================================
// 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 2014 Sandia Corporation.
// Copyright 2014 UT-Battelle, LLC.
// Copyright 2014. 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.
//============================================================================
// This tests a previous problem where code templated on the device adapter and
// used one of the device adapter algorithms (for example, the dispatcher) had
// to be declared after any device adapter it was ever used with.
#define VTKM_DEVICE_ADAPTER VTKM_DEVICE_ADAPTER_ERROR
#include <vtkm/cont/DeviceAdapter.h>
#include <vtkm/cont/testing/Testing.h>
#include <vtkm/cont/ArrayHandle.h>
// Important for this test!
//This file must be included after ArrayHandle.h
#include <vtkm/cont/DeviceAdapterSerial.h>
namespace {
struct ExampleWorklet
{
template <typename T>
void operator()(T vtkmNotUsed(v)) const { }
};
void CheckPostDefinedDeviceAdapter()
{
// Nothing to really check. If this compiles, then the test is probably
// successful.
vtkm::cont::ArrayHandle<vtkm::Id> test;
}
} // anonymous namespace
int UnitTestDeviceAdapterAlgorithmDependency(int, char *[])
{
return vtkm::cont::testing::Testing::Run(CheckPostDefinedDeviceAdapter);
}

@ -0,0 +1,106 @@
//============================================================================
// 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 2014 Sandia Corporation.
// Copyright 2014 UT-Battelle, LLC.
// Copyright 2014. 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.
//============================================================================
// This test makes sure that the algorithms specified in
// DeviceAdapterAlgorithmGeneral.h are working correctly. It does this by
// creating a test device adapter that uses the serial device adapter for the
// base schedule/scan/sort algorithms and using the general algorithms for
// everything else. Because this test is based of the serial device adapter,
// make sure that UnitTestDeviceAdapterSerial is working before trying to debug
// this one.
#define VTKM_DEVICE_ADAPTER VTKM_DEVICE_ADAPTER_ERROR
#include <vtkm/cont/DeviceAdapterSerial.h>
#include <vtkm/cont/internal/DeviceAdapterAlgorithmGeneral.h>
#include <vtkm/cont/testing/TestingDeviceAdapter.h>
VTKM_CREATE_DEVICE_ADAPTER(TestAlgorithmGeneral);
namespace vtkm {
namespace cont {
template<>
struct DeviceAdapterAlgorithm<
vtkm::cont::DeviceAdapterTagTestAlgorithmGeneral> :
vtkm::cont::internal::DeviceAdapterAlgorithmGeneral<
DeviceAdapterAlgorithm<
vtkm::cont::DeviceAdapterTagTestAlgorithmGeneral>,
vtkm::cont::DeviceAdapterTagTestAlgorithmGeneral>
{
private:
typedef vtkm::cont::DeviceAdapterAlgorithm<
vtkm::cont::DeviceAdapterTagSerial> Algorithm;
typedef vtkm::cont::DeviceAdapterTagTestAlgorithmGeneral
DeviceAdapterTagTestAlgorithmGeneral;
public:
template<class Functor>
VTKM_CONT_EXPORT static void Schedule(Functor functor,
vtkm::Id numInstances)
{
Algorithm::Schedule(functor, numInstances);
}
template<class Functor>
VTKM_CONT_EXPORT static void Schedule(Functor functor,
vtkm::Id3 rangeMax)
{
Algorithm::Schedule(functor, rangeMax);
}
VTKM_CONT_EXPORT static void Synchronize()
{
Algorithm::Synchronize();
}
};
namespace internal {
template <typename T, class ArrayContainerControlTag>
class ArrayManagerExecution
<T,
ArrayContainerControlTag,
vtkm::cont::DeviceAdapterTagTestAlgorithmGeneral>
: public vtkm::cont::internal::ArrayManagerExecution
<T, ArrayContainerControlTag, vtkm::cont::DeviceAdapterTagSerial>
{
public:
typedef vtkm::cont::internal::ArrayManagerExecution
<T, ArrayContainerControlTag, vtkm::cont::DeviceAdapterTagSerial>
Superclass;
typedef typename Superclass::ValueType ValueType;
typedef typename Superclass::PortalType PortalType;
typedef typename Superclass::PortalConstType PortalConstType;
};
}
}
} // namespace vtkm::cont::testing
int UnitTestDeviceAdapterAlgorithmGeneral(int, char *[])
{
return vtkm::cont::testing::TestingDeviceAdapter
<vtkm::cont::DeviceAdapterTagTestAlgorithmGeneral>::Run();
}

@ -0,0 +1,31 @@
//============================================================================
// 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 2014 Sandia Corporation.
// Copyright 2014 UT-Battelle, LLC.
// Copyright 2014. 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.
//============================================================================
#define VTKM_DEVICE_ADAPTER VTKM_DEVICE_ADAPTER_ERROR
#include <vtkm/cont/DeviceAdapterSerial.h>
#include <vtkm/cont/testing/TestingDeviceAdapter.h>
int UnitTestDeviceAdapterSerial(int, char *[])
{
return vtkm::cont::testing::TestingDeviceAdapter
<vtkm::cont::DeviceAdapterTagSerial>::Run();
}

@ -0,0 +1,94 @@
//============================================================================
// 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 2014 Sandia Corporation.
// Copyright 2014 UT-Battelle, LLC.
// Copyright 2014. 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 vtkm_exec_internal_ErrorMessageBuffer_h
#define vtkm_exec_internal_ErrorMessageBuffer_h
#include <vtkm/Types.h>
namespace vtkm {
namespace exec {
namespace internal {
/// Used to hold an error in the execution environment until the parallel
/// execution can complete. This is to be used in conjunction with a
/// DeviceAdapter's Schedule function to implement errors in execution
/// environments that cannot throw errors. This string should be global to all
/// threads. If the first entry in the string is '\0' (the C string
/// terminator), then we consider it as no error. Otherwise, the array contains
/// the string describing the error.
///
/// Before scheduling worklets, the global array should be cleared to have no
/// error. This can only be reliably done by the device adapter.
///
class ErrorMessageBuffer
{
public:
VTKM_EXEC_CONT_EXPORT ErrorMessageBuffer()
: MessageBuffer(), MessageBufferSize(0) { }
VTKM_EXEC_CONT_EXPORT
ErrorMessageBuffer(char *messageBuffer, vtkm::Id bufferSize)
: MessageBuffer(messageBuffer), MessageBufferSize(bufferSize) { }
VTKM_EXEC_EXPORT void RaiseError(const char *message) const
{
// Only raise the error if one has not been raised yet. This check is not
// guaranteed to work across threads. However, chances are that if two or
// more threads simultaneously pass this test, they will be writing the
// same error, which is fine. Even in the much less likely case that two
// threads simultaneously write different error messages, the worst case is
// that you get a mangled message. That's not good (and it's what we are
// trying to avoid), but it's not critical.
if (this->IsErrorRaised()) { return; }
// Safely copy message into array.
for (vtkm::Id index = 0; index < this->MessageBufferSize; index++)
{
this->MessageBuffer[index] = message[index];
if (message[index] == '\0') { break; }
}
// Make sure message is null terminated.
this->MessageBuffer[this->MessageBufferSize-1] = '\0';
}
VTKM_EXEC_CONT_EXPORT bool IsErrorRaised() const
{
if (this->MessageBufferSize > 0)
{
return (this->MessageBuffer[0] != '\0');
}
else
{
// If there is no buffer set, then always report an error.
return true;
}
}
private:
char *MessageBuffer;
vtkm::Id MessageBufferSize;
};
}
}
} // namespace vtkm::exec::internal
#endif // vtkm_exec_internal_ErrorMessageBuffer_h

@ -0,0 +1,64 @@
//============================================================================
// 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 2014 Sandia Corporation.
// Copyright 2014 UT-Battelle, LLC.
// Copyright 2014. 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 vtkm_exec_WorkletBase_h
#define vtkm_exec_WorkletBase_h
#include <vtkm/Types.h>
#include <vtkm/exec/internal/ErrorMessageBuffer.h>
namespace vtkm {
namespace exec {
namespace internal {
/// Base class for all worklet classes. Worklet classes are subclasses and a
/// operator() const is added to implement an algorithm in Dax. Different
/// worklets have different calling semantics.
///
class WorkletBase
{
public:
VTKM_EXEC_CONT_EXPORT WorkletBase() { }
VTKM_EXEC_EXPORT void RaiseError(const char *message) const
{
this->ErrorMessage.RaiseError(message);
}
/// Set the error message buffer so that running algorithms can report
/// errors. This is supposed to be set by the dispatcher. This method may be
/// replaced as the execution semantics change.
///
VTKM_CONT_EXPORT void SetErrorMessageBuffer(
const vtkm::exec::internal::ErrorMessageBuffer &buffer)
{
this->ErrorMessage = buffer;
}
private:
vtkm::exec::internal::ErrorMessageBuffer ErrorMessage;
};
}
}
} // namespace vtkm::exec::internal
#endif //vtkm_exec_WorkletBase_h

@ -29,6 +29,7 @@ set(unit_tests
UnitTestTesting.cxx
UnitTestTypes.cxx
UnitTestTypeTraits.cxx
UnitTestVectorTraits.cxx
)
VTKM_unit_tests(SOURCES ${unit_tests})

@ -0,0 +1,63 @@
//============================================================================
// 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 2014 Sandia Corporation.
// Copyright 2014 UT-Battelle, LLC.
// Copyright 2014. 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.
//============================================================================
#include <vtkm/testing/VectorTraitsTests.h>
#include <vtkm/testing/Testing.h>
namespace {
static const vtkm::Id MAX_VECTOR_SIZE = 5;
static const vtkm::Id VectorInit[MAX_VECTOR_SIZE] = { 42, 54, 67, 12, 78 };
struct TestVectorTypeFunctor
{
template <typename T> void operator()(const T&) const {
typedef vtkm::VectorTraits<T> Traits;
VTKM_TEST_ASSERT(Traits::NUM_COMPONENTS <= MAX_VECTOR_SIZE,
"Need to update test for larger vectors.");
T vector;
for (int index = 0; index < Traits::NUM_COMPONENTS; index++)
{
Traits::SetComponent(vector, index, VectorInit[index]);
}
vtkm::testing::TestVectorType(vector);
}
};
void TestVectorTraits()
{
TestVectorTypeFunctor test;
vtkm::testing::Testing::TryAllTypes(test);
std::cout << "vtkm::Tuple<vtkm::Scalar, 5>" << std::endl;
test(vtkm::Tuple<vtkm::Scalar,5>());
vtkm::testing::TestVectorComponentsTag<vtkm::Id3>();
vtkm::testing::TestVectorComponentsTag<vtkm::Vector3>();
vtkm::testing::TestVectorComponentsTag<vtkm::Vector4>();
vtkm::testing::TestScalarComponentsTag<vtkm::Id>();
vtkm::testing::TestScalarComponentsTag<vtkm::Scalar>();
}
} // anonymous namespace
int UnitTestVectorTraits(int, char *[])
{
return vtkm::testing::Testing::Run(TestVectorTraits);
}

@ -0,0 +1,157 @@
//============================================================================
// 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 2014 Sandia Corporation.
// Copyright 2014 UT-Battelle, LLC.
// Copyright 2014. 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 vtkm_testing_VectorTraitsTest_h
#define vtkm_testing_VectorTraitsTest_h
#include <vtkm/VectorTraits.h>
#include <vtkm/TypeTraits.h>
#include <vtkm/testing/Testing.h>
#include <boost/type_traits/remove_const.hpp>
namespace vtkm {
namespace testing {
namespace detail {
inline void CompareDimensionalityTags(vtkm::TypeTraitsScalarTag,
vtkm::VectorTraitsTagSingleComponent)
{
// If we are here, everything is fine.
}
inline void CompareDimensionalityTags(vtkm::TypeTraitsVectorTag,
vtkm::VectorTraitsTagMultipleComponents)
{
// If we are here, everything is fine.
}
/// Compares some manual arithmetic through type traits to arithmetic with
/// the Tuple class.
template <class T>
static void TestVectorTypeImpl(
const typename boost::remove_const<T>::type &vector)
{
typedef typename vtkm::VectorTraits<T> Traits;
typedef typename Traits::ComponentType ComponentType;
static const int NUM_COMPONENTS = Traits::NUM_COMPONENTS;
typedef typename boost::remove_const<T>::type NonConstT;
{
NonConstT result;
const ComponentType multiplier = 4;
for (int i = 0; i < NUM_COMPONENTS; i++)
{
Traits::SetComponent(result, i, multiplier*Traits::GetComponent(vector, i));
}
VTKM_TEST_ASSERT(test_equal(Traits::ToTuple(result),
multiplier*Traits::ToTuple(vector)),
"Got bad result for scalar multiple");
}
{
NonConstT result;
const ComponentType multiplier = 7;
for (int i = 0; i < NUM_COMPONENTS; i++)
{
Traits::GetComponent(result, i)
= multiplier * Traits::GetComponent(vector, i);
}
VTKM_TEST_ASSERT(test_equal(Traits::ToTuple(result),
multiplier*Traits::ToTuple(vector)),
"Got bad result for scalar multiple");
}
{
ComponentType result = 0;
for (int i = 0; i < NUM_COMPONENTS; i++)
{
ComponentType component
= Traits::GetComponent(vector, i);
result += component * component;
}
VTKM_TEST_ASSERT(
test_equal(result,
vtkm::dot(Traits::ToTuple(vector), Traits::ToTuple(vector))),
"Got bad result for dot product");
}
// This will fail to compile if the tags are wrong.
detail::CompareDimensionalityTags(
typename vtkm::TypeTraits<T>::DimensionalityTag(),
typename vtkm::VectorTraits<T>::HasMultipleComponents());
}
inline void CheckVectorComponentsTag(vtkm::VectorTraitsTagMultipleComponents)
{
// If we are running here, everything is fine.
}
} // namespace detail
/// Checks to make sure that the HasMultipleComponents tag is actually for
/// multiple components. Should only be called for vector classes that actually
/// have multiple components.
///
template<class T>
inline void TestVectorComponentsTag()
{
// This will fail to compile if the tag is wrong
// (i.e. not vtkm::VectorTraitsTagMultipleComponents)
detail::CheckVectorComponentsTag(
typename vtkm::VectorTraits<T>::HasMultipleComponents());
}
namespace detail {
inline void CheckScalarComponentsTag(vtkm::VectorTraitsTagSingleComponent)
{
// If we are running here, everything is fine.
}
} // namespace detail
/// Compares some manual arithmetic through type traits to arithmetic with
/// the Tuple class.
template <class T>
static void TestVectorType(const T &vector)
{
detail::TestVectorTypeImpl<T>(vector);
detail::TestVectorTypeImpl<const T>(vector);
}
/// Checks to make sure that the HasMultipleComponents tag is actually for a
/// single component. Should only be called for "vector" classes that actually
/// have only a single component (that is, are really scalars).
///
template<class T>
inline void TestScalarComponentsTag()
{
// This will fail to compile if the tag is wrong
// (i.e. not vtkm::VectorTraitsTagSingleComponent)
detail::CheckScalarComponentsTag(
typename vtkm::VectorTraits<T>::HasMultipleComponents());
}
}
} // namespace vtkm::testing
#endif //vtkm_testing_VectorTraitsTest_h