vtk-m/vtkm/cont/kokkos/internal/KokkosAlloc.cxx
Kenneth Moreland 9855db0961 Add test for array and datas that are cleaned up after finalize
It is the case that arrays might be deallocated from a device after the
device is closed. This can happen, for example, when an `ArrayHandle` is
declared globally. It gets constructed before VTK-m is initialized. This
is OK as long as you do not otherwise use it until VTK-m is initialized.
However, if you use that `ArrayHandle` to move data to a device and that
data is left on the device when the object closes, then the
`ArrayHandle` will be left holding a reference to invalid device memory
once the device is shut down. This can cause problems when the
`ArrayHandle` destructs itself and attempts to release this memory.

The VTK-m devices should gracefully handle deallocations that happen
after device shutdown.
2022-07-01 12:36:55 -06:00

72 lines
1.7 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.
//============================================================================
#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)
{
if (Kokkos::is_initialized())
{
GetExecutionSpaceInstance().fence();
Kokkos::kokkos_free<ExecutionSpace::memory_space>(ptr);
}
else
{
// It is possible that a Buffer instance might try to free its Kokkos data after
// Kokkos has been finalized. If that is the case, silently do nothing.
}
}
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