vtk-m/vtkm/cont/internal/ArrayManagerExecution.h
hschroot 20c1a04894 CopyInto function for ArrayHandles
ArrayHandles in DAX have a CopyInto function which allows the user to copy an array handle's data into a compatible STL type iterator. Originally this was fairly straight forward to implement since array handles in DAX are templated on the DeviceAdapterTag. In contrast, VTKm array handles use a polymorphic ArrayHandleExecutionManager under the hood allowing a single array handle to interface with multiple devices at runtime. To achieve this virtual functions are used. This makes implementing the CopyInto function difficult since it is templated on the IteratorType and virtual functions cannot be templated.

To work around this, I've implemented a concrete templated CopyInto function in the class derived from ArrayHandleExecutionManagerBase. In the ArrayHandle class, CopyInto dynamically casts the base class into the derived class, then calls the CopyInto function defined in the derived class.

The drawback to this approach is that, should the user define their own class that inherits from ArrayHandleExectionManagerBase, they are not forced to implement the CopyInto function, unlike the other virtual functions.
2015-09-17 14:26:19 -04:00

179 lines
7.2 KiB
C++

//============================================================================
// 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 vtk_m_cont_internal_ArrayManagerExecution_h
#define vtk_m_cont_internal_ArrayManagerExecution_h
#include <vtkm/cont/internal/DeviceAdapterTag.h>
namespace vtkm {
namespace cont {
namespace internal {
/// \brief Class that manages data in the execution environment.
///
/// This templated class must be partially specialized for each
/// DeviceAdapterTag crated, which will define the implementation for that tag.
///
/// This is a class that is responsible for allocating data in the execution
/// environment and copying data back and forth between control and
/// execution. It is also expected that this class will automatically release
/// any resources in its destructor.
///
/// This class typically takes on one of two forms. If the control and
/// execution environments have seperate memory spaces, then this class
/// behaves how you would expect. It allocates/deallocates arrays and copies
/// data. However, if the control and execution environments share the same
/// memory space, this class should delegate all its operations to the
/// \c Storage. The latter can probably be implemented with a
/// trivial subclass of
/// vtkm::cont::internal::ArrayManagerExecutionShareWithControl.
///
template<typename T, class StorageTag, class DeviceAdapterTag>
class ArrayManagerExecution
#ifdef VTKM_DOXYGEN_ONLY
{
private:
typedef vtkm::cont::internal::Storage<T,StorageTag> StorageType;
public:
/// The type of value held in the array (vtkm::FloatDefault, vtkm::Vec, etc.)
///
typedef T ValueType;
/// An array portal that can be used in the execution environment to access
/// portions of the arrays. This example defines the portal with a pointer,
/// but any portal with methods that can be called and data that can be
/// accessed from the execution environment can be used.
///
typedef vtkm::exec::internal::ArrayPortalFromIterators<ValueType*> PortalType;
/// Const version of PortalType. You must be able to cast PortalType to
/// PortalConstType.
///
typedef vtkm::exec::internal::ArrayPortalFromIterators<const ValueType*>
PortalConstType;
/// All ArrayManagerExecution classes must have a constructor that takes a
/// storage reference. The reference may be saved (and will remain valid
/// throughout the life of the ArrayManagerExecution). Copying storage
/// objects should be avoided (copy references or pointers only). The
/// reference can also, of course, be ignored.
///
VTKM_CONT_EXPORT
ArrayManagerExecution(vtkm::cont::internal::Storage<T,StorageTag> &storage);
/// Returns the number of values stored in the array. Results are undefined
/// if data has not been loaded or allocated.
///
VTKM_CONT_EXPORT
vtkm::Id GetNumberOfValues() const;
/// Prepares the data for use as input in the execution environment. If the
/// flag \c updateData is true, then data is transferred to the execution
/// environment. Otherwise, this transfer should be skipped.
///
/// Returns a constant array portal valid in the execution environment.
///
VTKM_CONT_EXPORT
PortalConstExecution PrepareForInput(bool updateData);
/// Prepares the data for use as both input and output in the execution
/// environment. If the flag \c updateData is true, then data is transferred
/// to the execution environment. Otherwise, this transfer should be skipped.
///
/// Returns a read-write array portal valid in the execution environment.
///
VTKM_CONT_EXPORT
PortalExecution LoadDataForInPlace(bool updateData);
/// Allocates an array in the execution environment of the specified size. If
/// control and execution share arrays, then this class can allocate data
/// using the given Storage it can be used directly in the execution
/// environment.
///
/// Returns a writable array portal valid in the execution environment.
///
VTKM_CONT_EXPORT
PortalExecution PrepareForOutput(vtkm::Id numberOfValues);
/// Allocates data in the given Storage and copies data held in the execution
/// environment (managed by this class) into the storage object. The
/// reference to the storage given is the same as that passed to the
/// constructor. If control and execution share arrays, this can be no
/// operation. This method should only be called after PrepareForOutput is
/// called.
///
VTKM_CONT_EXPORT
void RetrieveOutputData(
vtkm::cont::internal::Storage<T,StorageTag>* storage) const;
/// Similar to RetrieveOutputData except that instead of writing to the
/// controlArray itself, it writes to the given control environment
/// iterator. This allows the user to retrieve data without necessarily
/// allocating an array in the ArrayContainerControl (assuming that control
/// and exeuction have seperate memory spaces).
///
template <class IteratorTypeControl>
VTKM_CONT_EXPORT void CopyInto(IteratorTypeControl dest) const;
/// \brief Reduces the size of the array without changing its values.
///
/// This method allows you to resize the array without reallocating it. The
/// number of entries in the array is changed to \c numberOfValues. The data
/// in the array (from indices 0 to \c numberOfValues - 1) are the same, but
/// \c numberOfValues must be equal or less than the preexisting size
/// (returned from GetNumberOfValues). That is, this method can only be used
/// to shorten the array, not lengthen.
///
VTKM_CONT_EXPORT
void Shrink(vtkm::Id numberOfValues);
/// Frees any resources (i.e. memory) allocated for the exeuction
/// environment, if any.
///
VTKM_CONT_EXPORT
void ReleaseResources();
};
#else // VTKM_DOXGEN_ONLY
;
#endif // VTKM_DOXYGEN_ONLY
}
}
} // namespace vtkm::cont::internal
//-----------------------------------------------------------------------------
// These includes are intentionally placed here after the declaration of the
// ArrayManagerExecution template prototype, which all the implementations
// need.
#if VTKM_DEVICE_ADAPTER == VTKM_DEVICE_ADAPTER_SERIAL
#include <vtkm/cont/internal/ArrayManagerExecutionSerial.h>
#elif VTKM_DEVICE_ADAPTER == VTKM_DEVICE_ADAPTER_CUDA
#include <vtkm/cont/cuda/internal/ArrayManagerExecutionCuda.h>
// #elif VTKM_DEVICE_ADAPTER == VTKM_DEVICE_ADAPTER_OPENMP
// #include <vtkm/openmp/cont/internal/ArrayManagerExecutionOpenMP.h>
#elif VTKM_DEVICE_ADAPTER == VTKM_DEVICE_ADAPTER_TBB
#include <vtkm/cont/tbb/internal/ArrayManagerExecutionTBB.h>
#endif
#endif //vtk_m_cont_internal_ArrayManagerExecution_h