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:
parent
6971989781
commit
89e19ce7fa
@ -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)
|
||||
|
78
vtkm/cont/kokkos/internal/DeviceAdapterAlgorithmKokkos.cxx
Normal file
78
vtkm/cont/kokkos/internal/DeviceAdapterAlgorithmKokkos.cxx
Normal file
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
63
vtkm/cont/kokkos/internal/KokkosAlloc.cxx
Normal file
63
vtkm/cont/kokkos/internal/KokkosAlloc.cxx
Normal file
@ -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
|
35
vtkm/cont/kokkos/internal/KokkosAlloc.h
Normal file
35
vtkm/cont/kokkos/internal/KokkosAlloc.h
Normal file
@ -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
|
36
vtkm/cont/kokkos/internal/KokkosTypes.cxx
Normal file
36
vtkm/cont/kokkos/internal/KokkosTypes.cxx
Normal file
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user