Don't require CUDA_LAUNCH_BLOCKING

1. The code now works without CUDA_LAUNCH_BLOCKING set by using explicit
   synchronizations where required.
2. The code has also been modified to use thread specific memory spaces,
   which for Kokkos' Cuda backend means per thread streams.
This commit is contained in:
Sujin Philip 2020-11-24 15:11:06 -05:00
parent 6971989781
commit 89e19ce7fa
11 changed files with 312 additions and 98 deletions

@ -220,5 +220,3 @@ test:ubuntu1804_kokkos:
- build:ubuntu1804_kokkos
needs:
- build:ubuntu1804_kokkos
variables:
CUDA_LAUNCH_BLOCKING: "1"

@ -17,14 +17,11 @@
#include <vtkm/cont/Storage.h>
#include <vtkm/cont/kokkos/internal/DeviceAdapterTagKokkos.h>
#include <vtkm/cont/kokkos/internal/ViewTypes.h>
#include <vtkm/cont/kokkos/internal/KokkosAlloc.h>
#include <vtkm/cont/kokkos/internal/KokkosTypes.h>
#include <vtkm/internal/ArrayPortalBasic.h>
VTKM_THIRDPARTY_PRE_INCLUDE
#include <Kokkos_Core.hpp>
VTKM_THIRDPARTY_POST_INCLUDE
#include <limits>
// These must be placed in the vtkm::cont::internal namespace so that
@ -105,7 +102,14 @@ public:
vtkm::cont::kokkos::internal::KokkosViewConstExec<T> deviceView(
this->DeviceArray, static_cast<std::size_t>(this->DeviceArrayLength));
auto hostView = Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace{}, deviceView);
auto hostView = Kokkos::create_mirror_view(deviceView);
if (hostView.data() != deviceView.data())
{
Kokkos::realloc(hostView, this->DeviceArrayLength);
Kokkos::deep_copy(
vtkm::cont::kokkos::internal::GetExecutionSpaceInstance(), hostView, deviceView);
}
vtkm::cont::kokkos::internal::GetExecutionSpaceInstance().fence();
storage->Allocate(this->DeviceArrayLength);
std::copy_n(hostView.data(),
@ -128,7 +132,7 @@ public:
///
VTKM_CONT void ReleaseResources()
{
Kokkos::kokkos_free(this->DeviceArray);
vtkm::cont::kokkos::internal::Free(this->DeviceArray);
this->DeviceArray = nullptr;
this->DeviceArrayLength = 0;
}
@ -144,11 +148,12 @@ private:
{
if (!this->DeviceArray)
{
this->DeviceArray = static_cast<T*>(Kokkos::kokkos_malloc(size));
this->DeviceArray = static_cast<T*>(vtkm::cont::kokkos::internal::Allocate(size));
}
else
{
this->DeviceArray = static_cast<T*>(Kokkos::kokkos_realloc(this->DeviceArray, size));
this->DeviceArray =
static_cast<T*>(vtkm::cont::kokkos::internal::Reallocate(this->DeviceArray, size));
}
}
catch (...)
@ -171,7 +176,8 @@ private:
vtkm::cont::kokkos::internal::KokkosViewExec<T> deviceView(self->DeviceArray,
self->DeviceArrayLength);
Kokkos::deep_copy(deviceView, hostView);
Kokkos::deep_copy(
vtkm::cont::kokkos::internal::GetExecutionSpaceInstance(), deviceView, hostView);
}
template <typename S>
@ -190,7 +196,8 @@ private:
vtkm::cont::kokkos::internal::KokkosViewExec<T> deviceView(
self->DeviceArray, static_cast<std::size_t>(self->DeviceArrayLength));
Kokkos::deep_copy(deviceView, hostView);
Kokkos::deep_copy(
vtkm::cont::kokkos::internal::GetExecutionSpaceInstance(), deviceView, hostView);
}
VTKM_CONT

@ -15,16 +15,20 @@ set(headers
DeviceAdapterRuntimeDetectorKokkos.h
DeviceAdapterTagKokkos.h
Initialize.h
ViewTypes.h
KokkosAlloc.h
KokkosTypes.h
VirtualObjectTransferKokkos.h)
vtkm_declare_headers(${headers})
if (TARGET vtkm::kokkos)
set(sources
${CMAKE_CURRENT_SOURCE_DIR}/DeviceAdapterAlgorithmKokkos.cxx
${CMAKE_CURRENT_SOURCE_DIR}/DeviceAdapterMemoryManagerKokkos.cxx
${CMAKE_CURRENT_SOURCE_DIR}/DeviceAdapterRuntimeDetectorKokkos.cxx
${CMAKE_CURRENT_SOURCE_DIR}/Initialize.cxx)
${CMAKE_CURRENT_SOURCE_DIR}/Initialize.cxx
${CMAKE_CURRENT_SOURCE_DIR}/KokkosAlloc.cxx
${CMAKE_CURRENT_SOURCE_DIR}/KokkosTypes.cxx)
target_sources(vtkm_cont PRIVATE ${sources})
if (TARGET vtkm::kokkos_cuda)

@ -0,0 +1,78 @@
//============================================================================
// 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.
//============================================================================
#include <vtkm/cont/kokkos/internal/DeviceAdapterAlgorithmKokkos.h>
#include <string>
namespace
{
constexpr static vtkm::Id ErrorMessageMaxLength = 1024;
using ErrorMessageView = vtkm::cont::kokkos::internal::KokkosViewExec<char>;
ErrorMessageView GetErrorMessageViewInstance()
{
static thread_local ErrorMessageView local(std::string("ErrorMessageViewInstance"),
ErrorMessageMaxLength);
return local;
}
} // anonymous namespace
namespace vtkm
{
namespace cont
{
vtkm::exec::internal::ErrorMessageBuffer
DeviceAdapterAlgorithm<vtkm::cont::DeviceAdapterTagKokkos>::GetErrorMessageBufferInstance()
{
return vtkm::exec::internal::ErrorMessageBuffer(GetErrorMessageViewInstance().data(),
ErrorMessageMaxLength);
}
void DeviceAdapterAlgorithm<vtkm::cont::DeviceAdapterTagKokkos>::CheckForErrors()
{
static thread_local char hostBuffer[ErrorMessageMaxLength] = "";
auto deviceView = GetErrorMessageViewInstance();
if (Kokkos::SpaceAccessibility<Kokkos::HostSpace, decltype(deviceView)::memory_space>::accessible)
{
vtkm::cont::kokkos::internal::GetExecutionSpaceInstance().fence();
if (deviceView(0) != '\0')
{
auto excep = vtkm::cont::ErrorExecution(deviceView.data());
deviceView(0) = '\0'; // clear
vtkm::cont::kokkos::internal::GetExecutionSpaceInstance().fence();
throw excep;
}
}
else
{
vtkm::cont::kokkos::internal::KokkosViewCont<char> hostView(hostBuffer, ErrorMessageMaxLength);
Kokkos::deep_copy(
vtkm::cont::kokkos::internal::GetExecutionSpaceInstance(), hostView, deviceView);
vtkm::cont::kokkos::internal::GetExecutionSpaceInstance().fence();
if (hostView(0) != '\0')
{
auto excep = vtkm::cont::ErrorExecution(hostView.data());
hostView(0) = '\0'; // clear
Kokkos::deep_copy(
vtkm::cont::kokkos::internal::GetExecutionSpaceInstance(), deviceView, hostView);
throw excep;
}
}
}
}
} // vtkm::cont

@ -16,8 +16,10 @@
#include <vtkm/cont/ArrayHandleIndex.h>
#include <vtkm/cont/ErrorExecution.h>
#include <vtkm/cont/internal/DeviceAdapterAlgorithmGeneral.h>
#include <vtkm/cont/vtkm_cont_export.h>
#include <vtkm/cont/kokkos/internal/DeviceAdapterTagKokkos.h>
#include <vtkm/cont/kokkos/internal/KokkosTypes.h>
#include <vtkm/exec/kokkos/internal/TaskBasic.h>
@ -95,21 +97,8 @@ private:
DeviceAdapterAlgorithm<vtkm::cont::DeviceAdapterTagKokkos>,
vtkm::cont::DeviceAdapterTagKokkos>;
constexpr static vtkm::Id ErrorMessageMaxLength = 1024;
using ErrorMessageStorage =
Kokkos::DualView<char*, Kokkos::LayoutLeft, Kokkos::DefaultExecutionSpace>;
VTKM_CONT static void CheckForErrors(ErrorMessageStorage& errorMessageStorage)
{
errorMessageStorage.template modify<ErrorMessageStorage::execution_space>();
errorMessageStorage.template sync<ErrorMessageStorage::host_mirror_space>();
if (errorMessageStorage.h_view(0) != '\0')
{
auto excep = vtkm::cont::ErrorExecution(errorMessageStorage.h_view.data());
errorMessageStorage.h_view(0) = '\0'; // clear
throw excep;
}
}
VTKM_CONT_EXPORT static vtkm::exec::internal::ErrorMessageBuffer GetErrorMessageBufferInstance();
VTKM_CONT_EXPORT static void CheckForErrors();
public:
template <typename IndicesStorage>
@ -157,7 +146,7 @@ public:
kokkos::internal::KokkosViewConstExec<T> viewIn(portalIn.GetArray(), inSize);
kokkos::internal::KokkosViewExec<T> viewOut(portalOut.GetArray(), inSize);
Kokkos::deep_copy(Kokkos::DefaultExecutionSpace{}, viewOut, viewIn);
Kokkos::deep_copy(vtkm::cont::kokkos::internal::GetExecutionSpaceInstance(), viewOut, viewIn);
}
template <typename WType, typename IType>
@ -173,15 +162,12 @@ public:
return;
}
ErrorMessageStorage errorMessageStorage;
errorMessageStorage.realloc(ErrorMessageMaxLength);
vtkm::exec::internal::ErrorMessageBuffer errorMessage(errorMessageStorage.d_view.data(),
ErrorMessageMaxLength);
functor.SetErrorMessageBuffer(errorMessage);
functor.SetErrorMessageBuffer(GetErrorMessageBufferInstance());
Kokkos::parallel_for(static_cast<std::size_t>(numInstances), functor);
CheckForErrors(errorMessageStorage);
Kokkos::RangePolicy<vtkm::cont::kokkos::internal::ExecutionSpace, vtkm::Id> policy(
vtkm::cont::kokkos::internal::GetExecutionSpaceInstance(), 0, numInstances);
Kokkos::parallel_for(policy, functor);
CheckForErrors(); // synchronizes
}
template <typename WType, typename IType>
@ -197,21 +183,21 @@ public:
return;
}
ErrorMessageStorage errorMessageStorage;
errorMessageStorage.realloc(ErrorMessageMaxLength);
vtkm::exec::internal::ErrorMessageBuffer errorMessage(errorMessageStorage.d_view.data(),
ErrorMessageMaxLength);
functor.SetErrorMessageBuffer(errorMessage);
functor.SetErrorMessageBuffer(GetErrorMessageBufferInstance());
Kokkos::MDRangePolicy<vtkm::cont::kokkos::internal::ExecutionSpace,
Kokkos::Rank<3>,
Kokkos::IndexType<vtkm::Id>>
policy(vtkm::cont::kokkos::internal::GetExecutionSpaceInstance(),
{ 0, 0, 0 },
{ rangeMax[0], rangeMax[1], rangeMax[2] });
Kokkos::MDRangePolicy<Kokkos::Rank<3>, Kokkos::IndexType<vtkm::Id>> policy(
{ 0, 0, 0 }, { rangeMax[0], rangeMax[1], rangeMax[2] });
Kokkos::parallel_for(
policy, KOKKOS_LAMBDA(vtkm::Id i, vtkm::Id j, vtkm::Id k) {
auto flatIdx = i + (j * rangeMax[0]) + (k * rangeMax[0] * rangeMax[1]);
functor(vtkm::Id3(i, j, k), flatIdx);
});
CheckForErrors(errorMessageStorage);
CheckForErrors(); // synchronizes
}
template <class Functor>
@ -238,9 +224,16 @@ private:
{
vtkm::cont::Token token;
auto portal = values.PrepareForInPlace(vtkm::cont::DeviceAdapterTagKokkos{}, token);
kokkos::internal::KokkosViewExec<T> view(portal.GetArray(), portal.GetNumberOfValues());
// We use per-thread execution spaces so that the threads can execute independently without
// requiring global synchronizations.
// Currently, there is no way to specify the execution space for sort and therefore it
// executes in the default execution space.
// Therefore, we need explicit syncs here.
vtkm::cont::kokkos::internal::GetExecutionSpaceInstance().fence();
Kokkos::sort(view);
vtkm::cont::kokkos::internal::GetExecutionSpaceInstance().fence();
}
template <typename T>
@ -260,7 +253,10 @@ public:
SortImpl(values, comp, typename std::is_scalar<T>::type{});
}
VTKM_CONT static void Synchronize() {}
VTKM_CONT static void Synchronize()
{
vtkm::cont::kokkos::internal::GetExecutionSpaceInstance().fence();
}
};
template <>

@ -7,34 +7,23 @@
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the above copyright notice for more information.
//============================================================================
#include <vtkm/cont/kokkos/internal/DeviceAdapterMemoryManagerKokkos.h>
#include <vtkm/cont/kokkos/DeviceAdapterKokkos.h>
#include <vtkm/cont/kokkos/internal/ViewTypes.h>
#include <sstream>
#include <vtkm/cont/kokkos/internal/KokkosAlloc.h>
#include <vtkm/cont/kokkos/internal/KokkosTypes.h>
namespace
{
void* KokkosAllocate(vtkm::BufferSizeType size)
{
try
{
return Kokkos::kokkos_malloc(static_cast<std::size_t>(size));
}
catch (...) // the type of error thrown is not well documented
{
std::ostringstream err;
err << "Failed to allocate " << size << " bytes on Kokkos device";
throw vtkm::cont::ErrorBadAllocation(err.str());
}
return vtkm::cont::kokkos::internal::Allocate(static_cast<std::size_t>(size));
}
void KokkosDelete(void* memory)
{
Kokkos::kokkos_free(memory);
vtkm::cont::kokkos::internal::Free(memory);
}
void KokkosReallocate(void*& memory,
@ -45,16 +34,7 @@ void KokkosReallocate(void*& memory,
VTKM_ASSERT(memory == container);
if (newSize > oldSize)
{
try
{
memory = container = Kokkos::kokkos_realloc(memory, static_cast<std::size_t>(newSize));
}
catch (...)
{
std::ostringstream err;
err << "Failed to re-allocate " << newSize << " bytes on Kokkos device";
throw vtkm::cont::ErrorBadAllocation(err.str());
}
memory = container = vtkm::cont::kokkos::internal::Reallocate(container, newSize);
}
}
}
@ -108,7 +88,7 @@ void DeviceAdapterMemoryManager<vtkm::cont::DeviceAdapterTagKokkos>::CopyHostToD
static_cast<vtkm::UInt8*>(src.GetPointer()), static_cast<std::size_t>(size));
vtkm::cont::kokkos::internal::KokkosViewExec<vtkm::UInt8> destView(
static_cast<vtkm::UInt8*>(dest.GetPointer()), static_cast<std::size_t>(size));
Kokkos::deep_copy(destView, srcView);
Kokkos::deep_copy(vtkm::cont::kokkos::internal::GetExecutionSpaceInstance(), destView, srcView);
}
vtkm::cont::internal::BufferInfo
@ -140,7 +120,8 @@ void DeviceAdapterMemoryManager<vtkm::cont::DeviceAdapterTagKokkos>::CopyDeviceT
static_cast<vtkm::UInt8*>(src.GetPointer()), static_cast<std::size_t>(size));
vtkm::cont::kokkos::internal::KokkosViewCont<vtkm::UInt8> destView(
static_cast<vtkm::UInt8*>(dest.GetPointer()), static_cast<std::size_t>(size));
Kokkos::deep_copy(destView, srcView);
Kokkos::deep_copy(vtkm::cont::kokkos::internal::GetExecutionSpaceInstance(), destView, srcView);
vtkm::cont::kokkos::internal::GetExecutionSpaceInstance().fence();
}
vtkm::cont::internal::BufferInfo
@ -163,7 +144,7 @@ void DeviceAdapterMemoryManager<vtkm::cont::DeviceAdapterTagKokkos>::CopyDeviceT
static_cast<vtkm::UInt8*>(src.GetPointer()), static_cast<std::size_t>(size));
vtkm::cont::kokkos::internal::KokkosViewExec<vtkm::UInt8> destView(
static_cast<vtkm::UInt8*>(dest.GetPointer()), static_cast<std::size_t>(size));
Kokkos::deep_copy(destView, srcView);
Kokkos::deep_copy(vtkm::cont::kokkos::internal::GetExecutionSpaceInstance(), destView, srcView);
}
}
}

@ -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.
//============================================================================
#include <vtkm/cont/kokkos/internal/KokkosAlloc.h>
#include <vtkm/cont/ErrorBadAllocation.h>
#include <vtkm/cont/kokkos/internal/KokkosTypes.h>
#include <sstream>
namespace vtkm
{
namespace cont
{
namespace kokkos
{
namespace internal
{
void* Allocate(std::size_t size)
{
try
{
return Kokkos::kokkos_malloc<ExecutionSpace::memory_space>(size);
}
catch (...) // the type of error thrown is not well documented
{
std::ostringstream err;
err << "Failed to allocate " << size << " bytes on Kokkos device";
throw vtkm::cont::ErrorBadAllocation(err.str());
}
}
void Free(void* ptr)
{
GetExecutionSpaceInstance().fence();
Kokkos::kokkos_free<ExecutionSpace::memory_space>(ptr);
}
void* Reallocate(void* ptr, std::size_t newSize)
{
try
{
return Kokkos::kokkos_realloc<ExecutionSpace::memory_space>(ptr, newSize);
}
catch (...)
{
std::ostringstream err;
err << "Failed to re-allocate " << newSize << " bytes on Kokkos device";
throw vtkm::cont::ErrorBadAllocation(err.str());
}
}
}
}
}
} // vtkm::cont::kokkos::internal

@ -0,0 +1,35 @@
//============================================================================
// 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.
//============================================================================
#ifndef vtk_m_cont_kokkos_internal_KokkosAlloc_h
#define vtk_m_cont_kokkos_internal_KokkosAlloc_h
#include <vtkm/cont/vtkm_cont_export.h>
#include <cstddef>
namespace vtkm
{
namespace cont
{
namespace kokkos
{
namespace internal
{
VTKM_CONT_EXPORT void* Allocate(std::size_t size);
VTKM_CONT_EXPORT void Free(void* ptr);
VTKM_CONT_EXPORT void* Reallocate(void* ptr, std::size_t newSize);
}
}
}
} // vtkm::cont::kokkos::internal
#endif // vtk_m_cont_kokkos_internal_KokkosAlloc_h

@ -0,0 +1,36 @@
//============================================================================
// 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.
//============================================================================
#include <vtkm/cont/kokkos/internal/KokkosTypes.h>
namespace vtkm
{
namespace cont
{
namespace kokkos
{
namespace internal
{
const ExecutionSpace& GetExecutionSpaceInstance()
{
// We use per-thread execution spaces so that the threads can execute independently without
// requiring global synchronizations.
#if defined(VTKM_KOKKOS_CUDA)
static thread_local ExecutionSpace space(cudaStreamPerThread);
#else
static thread_local ExecutionSpace space;
#endif
return space;
}
}
}
}
} // vtkm::cont::kokkos::internal

@ -7,11 +7,11 @@
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the above copyright notice for more information.
//============================================================================
#ifndef vtk_m_cont_kokkos_internal_ViewTypes_h
#define vtk_m_cont_kokkos_internal_ViewTypes_h
#ifndef vtk_m_cont_kokkos_internal_KokkosTypes_h
#define vtk_m_cont_kokkos_internal_KokkosTypes_h
#include <vtkm/cont/ErrorBadAllocation.h>
#include <vtkm/cont/Logging.h>
#include <vtkm/cont/vtkm_cont_export.h>
#include <vtkm/internal/Configure.h>
VTKM_THIRDPARTY_PRE_INCLUDE
#include <Kokkos_Core.hpp>
@ -26,13 +26,17 @@ namespace kokkos
namespace internal
{
using ExecutionSpace = Kokkos::DefaultExecutionSpace;
VTKM_CONT_EXPORT const ExecutionSpace& GetExecutionSpaceInstance();
template <typename ValueType>
using KokkosViewCont = Kokkos::
View<ValueType*, Kokkos::LayoutRight, Kokkos::HostSpace, Kokkos::MemoryTraits<Kokkos::Unmanaged>>;
template <typename ValueType>
using KokkosViewExec =
decltype(Kokkos::create_mirror(Kokkos::DefaultExecutionSpace{}, KokkosViewCont<ValueType>{}));
decltype(Kokkos::create_mirror(ExecutionSpace{}, KokkosViewCont<ValueType>{}));
template <typename ValueType>
using KokkosViewConstCont = typename KokkosViewCont<ValueType>::const_type;
@ -42,6 +46,6 @@ using KokkosViewConstExec = typename KokkosViewExec<ValueType>::const_type;
}
}
}
} // vtkm::cont::kokkos::internaL
} // vtkm::cont::kokkos::internal
#endif // vtk_m_cont_kokkos_internal_ViewTypes_h
#endif // vtk_m_cont_kokkos_internal_KokkosTypes_h

@ -14,7 +14,8 @@
#include <vtkm/cont/internal/VirtualObjectTransfer.h>
#include <vtkm/cont/kokkos/internal/DeviceAdapterTagKokkos.h>
#include <vtkm/cont/kokkos/internal/ViewTypes.h>
#include <vtkm/cont/kokkos/internal/KokkosAlloc.h>
#include <vtkm/cont/kokkos/internal/KokkosTypes.h>
namespace vtkm
{
@ -45,17 +46,24 @@ struct VirtualObjectTransfer<VirtualDerivedType, vtkm::cont::DeviceAdapterTagKok
// will be wrong.
vtkm::cont::kokkos::internal::KokkosViewConstCont<vtkm::UInt8> hbuffer(
reinterpret_cast<const vtkm::UInt8*>(this->ControlObject), sizeof(VirtualDerivedType));
auto dbuffer = Kokkos::create_mirror_view_and_copy(Kokkos::DefaultExecutionSpace{}, hbuffer);
auto deviceTarget = reinterpret_cast<const VirtualDerivedType*>(dbuffer.data());
auto deviceTarget = static_cast<VirtualDerivedType*>(
vtkm::cont::kokkos::internal::Allocate(sizeof(VirtualDerivedType)));
vtkm::cont::kokkos::internal::KokkosViewExec<vtkm::UInt8> dbuffer(
reinterpret_cast<vtkm::UInt8*>(deviceTarget), sizeof(VirtualDerivedType));
Kokkos::deep_copy(
vtkm::cont::kokkos::internal::GetExecutionSpaceInstance(), dbuffer, hbuffer);
if (this->ExecutionObject == nullptr)
{
// Allocate memory for the object that will eventually be a correct copy on the device.
auto executionObjectPtr = this->ExecutionObject =
static_cast<VirtualDerivedType*>(Kokkos::kokkos_malloc(sizeof(VirtualDerivedType)));
auto executionObjectPtr = this->ExecutionObject = static_cast<VirtualDerivedType*>(
vtkm::cont::kokkos::internal::Allocate(sizeof(VirtualDerivedType)));
// Initialize the device object
Kokkos::RangePolicy<vtkm::cont::kokkos::internal::ExecutionSpace> policy(
vtkm::cont::kokkos::internal::GetExecutionSpaceInstance(), 0, 1);
Kokkos::parallel_for(
"ConstructVirtualObject", 1, KOKKOS_LAMBDA(const int&) {
"ConstructVirtualObject", policy, KOKKOS_LAMBDA(const int&) {
new (executionObjectPtr) VirtualDerivedType(*deviceTarget);
});
}
@ -63,11 +71,15 @@ struct VirtualObjectTransfer<VirtualDerivedType, vtkm::cont::DeviceAdapterTagKok
{
auto executionObjectPtr = this->ExecutionObject;
// Initialize the device object
Kokkos::RangePolicy<vtkm::cont::kokkos::internal::ExecutionSpace> policy(
vtkm::cont::kokkos::internal::GetExecutionSpaceInstance(), 0, 1);
Kokkos::parallel_for(
"UpdateVirtualObject", 1, KOKKOS_LAMBDA(const int&) {
"UpdateVirtualObject", policy, KOKKOS_LAMBDA(const int&) {
*executionObjectPtr = *deviceTarget;
});
}
vtkm::cont::kokkos::internal::Free(deviceTarget);
}
return this->ExecutionObject;
@ -80,13 +92,13 @@ struct VirtualObjectTransfer<VirtualDerivedType, vtkm::cont::DeviceAdapterTagKok
auto executionObjectPtr = this->ExecutionObject;
this->ExecutionObject = nullptr;
Kokkos::DefaultExecutionSpace execSpace;
Kokkos::RangePolicy<vtkm::cont::kokkos::internal::ExecutionSpace> policy(
vtkm::cont::kokkos::internal::GetExecutionSpaceInstance(), 0, 1);
Kokkos::parallel_for(
"DeleteVirtualObject",
Kokkos::RangePolicy<Kokkos::DefaultExecutionSpace>(execSpace, 0, 1),
KOKKOS_LAMBDA(const int&) { executionObjectPtr->~VirtualDerivedType(); });
execSpace.fence();
Kokkos::kokkos_free(executionObjectPtr);
"DeleteVirtualObject", policy, KOKKOS_LAMBDA(const int&) {
executionObjectPtr->~VirtualDerivedType();
});
vtkm::cont::kokkos::internal::Free(executionObjectPtr);
}
}