Commit bd337854 authored by Allison Vacanti's avatar Allison Vacanti

Initial implementation of general logging.

Addresses #291.
parent a754787e
......@@ -97,6 +97,7 @@ vtkm_option(VTKm_ENABLE_OPENMP "Enable OpenMP support" OFF)
vtkm_option(VTKm_ENABLE_RENDERING "Enable rendering library" ON)
vtkm_option(VTKm_ENABLE_TESTING "Enable VTKm Testing" ON)
vtkm_option(VTKm_ENABLE_BENCHMARKS "Enable VTKm Benchmarking" OFF)
vtkm_option(VTKm_ENABLE_LOGGING "Enable VTKm Logging" OFF)
vtkm_option(VTKm_ENABLE_MPI "Enable MPI support" OFF)
vtkm_option(VTKm_ENABLE_DOCUMENTATION "Build Doxygen documentation" OFF)
......
......@@ -32,6 +32,7 @@
#include <vtkm/cont/CellSetStructured.h>
#include <vtkm/cont/DataSet.h>
#include <vtkm/cont/ErrorInternal.h>
#include <vtkm/cont/Logging.h>
#include <vtkm/cont/RuntimeDeviceTracker.h>
#include <vtkm/cont/StorageBasic.h>
#include <vtkm/cont/Timer.h>
......@@ -1282,6 +1283,8 @@ int BenchmarkBody(int argc, char* argv[])
int main(int argc, char* argv[])
{
vtkm::cont::InitLogging(argc, argv);
int retval = 1;
try
{
......
# Logging support via loguru.
The loguru project has been integrated with VTK-m to provide runtime logging
facilities. A sample of the log output can be found at
https://gitlab.kitware.com/snippets/427.
Logging is enabled by setting the CMake variable VTKm_ENABLE_LOGGING. When
this flag is enabled, any messages logged to the Info, Warn, Error, and
Fatal levels are printed to stderr by default.
Additional logging features are enabled by calling vtkm::cont::InitLogging
in an executable. This will:
- Set human-readable names for the log levels in the output.
- Allow the stderr logging level to be set at runtime by passing a
'-v [level]' argument to the executable.
- Name the main thread.
- Print a preamble with details of the program's startup (args, etc).
- Install signal handlers to automatically print stacktraces and error
contexts (linux only) on crashes.
The main logging entry points are the macros VTKM_LOG_S and VTKM_LOG_F,
which using C++ stream and printf syntax, repectively. Other variants exist,
including conditional logging and special-purpose logs for writing specific
events, such as DynamicObject cast results and TryExecute failures.
The logging backend supports the concept of "Scopes". By creating a new
scope with the macros VTKM_LOG_SCOPE or VTKM_LOG_SCOPE_FUNCTION, a new
"logging scope" is opened within the C++ scope the macro is called from. New
messages will be indented in the log until the scope ends, at which point
a message is logged with the elapsed time that the scope was active. Scopes
may be nested to arbitrary depths.
The logging implementation is thread-safe. When working in a multithreaded
environment, each thread may be assigned a human-readable name using
vtkm::cont::SetThreadName. This will appear in the log output so that
per-thread messages can be easily tracked.
By default, only Info, Warn, Error, and Fatal messages are printed to
stderr. This can be changed at runtime by passing the '-v' flag to an
executable that calls vtkm::cont::InitLogging. Alternatively, the
application can explicitly call vtkm::cont::SetStderrLogLevel to change the
verbosity. When specifying a verbosity, all log levels with enum values
less-than-or-equal-to the requested level are printed.
vtkm::cont::LogLevel::Off (or "-v Off") may be used to silence the log
completely.
The helper functions vtkm::cont::GetHumanReadableSize and
vtkm::cont::GetSizeString assist in formating byte sizes to a more readable
format. Similarly, the vtkm::cont::TypeName template functions provide RTTI
based type-name information. When logging is enabled, these use the logging
backend to demangle symbol names on supported platforms.
The more verbose VTK-m log levels are:
- Perf: Logs performance information, using the scopes feature to track
execution time of filters, worklets, and device algorithms with
microsecond resolution.
- MemCont / MemExec: These levels log memory allocations in the control and
execution environments, respectively.
- MemTransfer: This level logs memory transfers between the control and host
environments.
- Cast: Logs details of dynamic object resolution.
The log may be shared and extended by applications that use VTK-m. There
are two log level ranges left available for applications: User and
UserVerbose. The User levels may be enabled without showing any of the
verbose VTK-m levels, while UserVerbose levels will also enable all VTK-m
levels.
......@@ -81,7 +81,9 @@ vtkm_declare_headers(
#first add all the components vtkm that are shared between control and exec
add_subdirectory(thirdparty/diy)
add_subdirectory(thirdparty/taotuple)
add_subdirectory(thirdparty/loguru) # TODO add cmake option to disable logging.
if(VTKm_ENABLE_LOGGING)
add_subdirectory(thirdparty/loguru)
endif()
add_subdirectory(testing)
add_subdirectory(internal)
......
......@@ -22,6 +22,7 @@
#include <vtkm/cont/ArrayHandle.h>
#include <vtkm/cont/ArrayHandleUniformPointCoordinates.h>
#include <vtkm/cont/Logging.h>
#include <vtkm/cont/TryExecute.h>
#include <vtkm/cont/VirtualObjectHandle.h>
#include <vtkm/cont/internal/DynamicTransform.h>
......@@ -480,8 +481,10 @@ public:
auto wrapper = this->GetArrayHandleWrapper<ArrayHandleType>();
if (!wrapper)
{
VTKM_LOG_CAST_FAIL(*this, ArrayHandleType);
throw vtkm::cont::ErrorBadType("dynamic cast failed");
}
VTKM_LOG_CAST_SUCC(*this, wrapper->GetArray());
return ArrayHandleType(wrapper->GetArray());
}
......
......@@ -89,6 +89,7 @@ set(headers
FieldRangeCompute.h
FieldRangeGlobalCompute.h
ImplicitFunctionHandle.h
Logging.h
MultiBlock.h
PointLocator.h
PointLocatorUniformGrid.h
......@@ -136,6 +137,7 @@ set(sources
internal/ArrayManagerExecutionShareWithControl.cxx
internal/DeviceAdapterTag.cxx
internal/SimplePolymorphicContainer.cxx
Logging.cxx
MultiBlock.cxx
PresetColorTables.cxx
RuntimeDeviceTracker.cxx
......
......@@ -27,6 +27,7 @@
#include <vtkm/cont/ArrayHandle.h>
#include <vtkm/cont/ErrorBadType.h>
#include <vtkm/cont/Logging.h>
#include <vtkm/cont/StorageListTag.h>
#include <vtkm/cont/ArrayHandlePermutation.h>
......@@ -266,11 +267,13 @@ public:
detail::DynamicArrayHandleTryCast<Type, Storage>(this->ArrayContainer);
if (downcastArray == nullptr)
{
VTKM_LOG_CAST_FAIL(*this, decltype(downcastArray));
throw vtkm::cont::ErrorBadType("Bad cast of dynamic array.");
}
// Technically, this method returns a copy of the \c ArrayHandle. But
// because \c ArrayHandle acts like a shared pointer, it is valid to
// do the copy.
VTKM_LOG_CAST_SUCC(*this, *downcastArray);
return *downcastArray;
}
......@@ -422,6 +425,7 @@ struct DynamicArrayHandleTry
downcastType downcastContainer = dynamic_cast<downcastType>(container);
if (downcastContainer)
{
VTKM_LOG_CAST_SUCC(*container, *downcastContainer);
f(downcastContainer->Array, std::forward<Args>(args)...);
called = true;
}
......@@ -473,6 +477,7 @@ VTKM_CONT void DynamicArrayHandleBase<TypeList, StorageList>::CastAndCall(Functo
if (!called)
{
// throw an exception
VTKM_LOG_CAST_FAIL(*this, crossProduct);
detail::ThrowCastAndCallException(ptr, &typeid(TypeList), &typeid(StorageList));
}
}
......
......@@ -23,6 +23,7 @@
#include <vtkm/cont/CellSet.h>
#include <vtkm/cont/CellSetListTag.h>
#include <vtkm/cont/ErrorBadValue.h>
#include <vtkm/cont/Logging.h>
#include <vtkm/cont/internal/DynamicTransform.h>
#include <vtkm/cont/internal/SimplePolymorphicContainer.h>
......@@ -186,8 +187,10 @@ public:
detail::DynamicCellSetTryCast<CellSetType>(this->CellSetContainer);
if (cellSetPointer == nullptr)
{
VTKM_LOG_CAST_FAIL(*this, CellSetType);
throw vtkm::cont::ErrorBadType("Bad cast of dynamic cell set.");
}
VTKM_LOG_CAST_SUCC(*this, *cellSetPointer);
return *cellSetPointer;
}
......@@ -289,6 +292,7 @@ struct DynamicCellSetTry
downcastType downcastContainer = dynamic_cast<downcastType>(this->Container);
if (downcastContainer)
{
VTKM_LOG_CAST_SUCC(*this->Container, *downcastContainer);
f(downcastContainer->Item, std::forward<Args>(args)...);
called = true;
}
......@@ -310,6 +314,7 @@ VTKM_CONT void DynamicCellSetBase<CellSetList>::CastAndCall(Functor&& f, Args&&.
tryCellSet, CellSetList{}, std::forward<Functor>(f), called, std::forward<Args>(args)...);
if (!called)
{
VTKM_LOG_CAST_FAIL(*this, CellSetList);
throw vtkm::cont::ErrorBadValue("Could not find appropriate cast for cell set.");
}
}
......
......@@ -27,6 +27,8 @@
#include <exception>
#include <string>
#include <vtkm/cont/Logging.h>
#include <vtkm/internal/ExportMacros.h>
namespace vtkm
......@@ -68,6 +70,9 @@ protected:
: Message(message)
, IsDeviceIndependent(is_device_independent)
{
VTKM_LOG_S(vtkm::cont::LogLevel::Warn,
"Exception raised: " << message << "\n"
<< vtkm::cont::GetStackTrace(1)); // 1 = skip this ctor frame.
}
void SetMessage(const std::string& message) { this->Message = message; }
......
//============================================================================
// 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 2018 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
// Copyright 2018 UT-Battelle, LLC.
// Copyright 2018 Los Alamos National Security.
//
// Under the terms of Contract DE-NA0003525 with NTESS,
// 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/cont/Logging.h>
#ifdef VTKM_ENABLE_LOGGING
// disable MSVC warnings in loguru.hpp
#ifdef VTKM_MSVC
#pragma warning(push)
#pragma warning(disable : 4722)
#endif // VTKM_MSVC
#define LOGURU_IMPLEMENTATION 1
#include <vtkm/thirdparty/loguru/vtkmloguru/loguru.hpp>
#ifdef VTKM_MSVC
#pragma warning(pop)
#endif // VTKM_MSVC
#endif // VTKM_ENABLE_LOGGING
#include <vtkm/testing/Testing.h> // for HumanSize
#include <cassert>
#include <unordered_map>
#ifdef VTKM_ENABLE_LOGGING
namespace
{
// This won't be needed under C++14, as strongly typed enums are automatically
// hashed then. But for now...
struct LogHasher
{
std::size_t operator()(vtkm::cont::LogLevel level) const
{
return static_cast<std::size_t>(level);
}
};
using LevelMapType = std::unordered_map<vtkm::cont::LogLevel, std::string, LogHasher>;
static bool Initialized = false;
static LevelMapType LogLevelNames;
void setLogLevelName(vtkm::cont::LogLevel level, const std::string& name)
{
// if the log has been initialized, prevent modifications of the name map
// to prevent race conditions.
if (!Initialized)
{
LogLevelNames[level] = name;
}
}
const char* verbosityToNameCallback(loguru::Verbosity verbosity)
{
const LevelMapType& names = LogLevelNames;
auto name = names.find(static_cast<vtkm::cont::LogLevel>(verbosity));
return name != names.end() ? name->second.c_str() : nullptr;
}
loguru::Verbosity nameToVerbosityCallback(const char* name)
{
const LevelMapType& names = LogLevelNames;
for (auto& kv : names)
{
if (kv.second == name)
{
return static_cast<loguru::Verbosity>(kv.first);
}
}
return loguru::Verbosity_INVALID;
}
} // end anon namespace
#endif // VTKM_ENABLE_LOGGING
namespace vtkm
{
namespace cont
{
VTKM_CONT
void InitLogging(int& argc, char* argv[])
{
#ifdef VTKM_ENABLE_LOGGING
SetLogLevelName(vtkm::cont::LogLevel::Off, "Off");
SetLogLevelName(vtkm::cont::LogLevel::Fatal, "FATL");
SetLogLevelName(vtkm::cont::LogLevel::Error, "ERR");
SetLogLevelName(vtkm::cont::LogLevel::Warn, "WARN");
SetLogLevelName(vtkm::cont::LogLevel::Info, "Info");
SetLogLevelName(vtkm::cont::LogLevel::Perf, "Perf");
SetLogLevelName(vtkm::cont::LogLevel::MemCont, "MemC");
SetLogLevelName(vtkm::cont::LogLevel::MemExec, "MemE");
SetLogLevelName(vtkm::cont::LogLevel::MemTransfer, "MemT");
SetLogLevelName(vtkm::cont::LogLevel::Cast, "Cast");
loguru::set_verbosity_to_name_callback(&verbosityToNameCallback);
loguru::set_name_to_verbosity_callback(&nameToVerbosityCallback);
loguru::init(argc, argv);
// Prevent LogLevelNames from being modified (makes thread safety easier)
Initialized = true;
LOG_F(INFO, "Logging initialized.");
#else // VTKM_ENABLE_LOGGING
(void)argc;
(void)argv;
#endif // VTKM_ENABLE_LOGGING
}
VTKM_CONT
void SetStderrLogLevel(LogLevel level)
{
#ifdef VTKM_ENABLE_LOGGING
loguru::g_stderr_verbosity = static_cast<loguru::Verbosity>(level);
#else // VTKM_ENABLE_LOGGING
(void)level;
#endif // VTKM_ENABLE_LOGGING
}
VTKM_CONT
void SetLogThreadName(const std::string& name)
{
#ifdef VTKM_ENABLE_LOGGING
loguru::set_thread_name(name.c_str());
#else // VTKM_ENABLE_LOGGING
(void)name;
#endif // VTKM_ENABLE_LOGGING
}
VTKM_CONT
std::string GetLogThreadName()
{
#ifdef VTKM_ENABLE_LOGGING
char buffer[128];
loguru::get_thread_name(buffer, 128, false);
return buffer;
#else // VTKM_ENABLE_LOGGING
return "N/A";
#endif // VTKM_ENABLE_LOGGING
}
VTKM_CONT
std::string GetLogErrorContext()
{
#ifdef VTKM_ENABLE_LOGGING
auto ctx = loguru::get_error_context();
return ctx.c_str();
#else // VTKM_ENABLE_LOGGING
return "N/A";
#endif // VTKM_ENABLE_LOGGING
}
VTKM_CONT
std::string GetStackTrace(vtkm::Int32 skip)
{
(void)skip; // unsed when logging disabled.
std::string result;
#ifdef VTKM_ENABLE_LOGGING
result = loguru::stacktrace(skip + 2).c_str();
#endif // VTKM_ENABLE_LOGGING
if (result.empty())
{
result = "(Stack trace unavailable)";
}
return result;
}
VTKM_CONT
std::string GetHumanReadableSize(vtkm::UInt64 bytes, int prec)
{
return HumanSize(bytes, prec);
}
VTKM_CONT
std::string GetSizeString(vtkm::UInt64 bytes, int prec)
{
return HumanSize(bytes, prec) + " (" + std::to_string(bytes) + " bytes)";
}
VTKM_CONT
void SetLogLevelName(LogLevel level, const std::string& name)
{
#ifdef VTKM_ENABLE_LOGGING
if (Initialized)
{
VTKM_LOG_F(LogLevel::Error, "SetLogLevelName called after InitLogging.");
return;
}
setLogLevelName(level, name);
#else // VTKM_ENABLE_LOGGING
(void)level;
(void)name;
#endif // VTKM_ENABLE_LOGGING
}
}
} // end namespace vtkm::cont
This diff is collapsed.
......@@ -19,6 +19,7 @@
//============================================================================
#define vtkm_cont_StorageBasic_cxx
#include <vtkm/cont/Logging.h>
#include <vtkm/cont/StorageBasic.h>
#include <vtkm/internal/Configure.h>
......@@ -218,8 +219,14 @@ void StorageBasicBase::AllocateValues(vtkm::Id numberOfValues, vtkm::UInt64 size
// Make sure our state is OK.
this->AllocatedByteSize = 0;
this->NumberOfValues = 0;
VTKM_LOG_F(vtkm::cont::LogLevel::MemCont,
"Could not allocate control array of %s.",
vtkm::cont::GetSizeString(allocsize).c_str());
throw vtkm::cont::ErrorBadAllocation("Could not allocate basic control array.");
}
VTKM_LOG_F(vtkm::cont::LogLevel::MemCont,
"Allocated control array of %s.",
vtkm::cont::GetSizeString(allocsize).c_str());
}
else
{
......@@ -246,6 +253,9 @@ void StorageBasicBase::ReleaseResources()
VTKM_ASSERT(this->Array != nullptr);
if (this->DeleteFunction)
{
VTKM_LOG_F(vtkm::cont::LogLevel::MemCont,
"Freeing control allocation of %s.",
vtkm::cont::GetSizeString(this->AllocatedByteSize).c_str());
this->DeleteFunction(this->Array);
}
this->Array = nullptr;
......
......@@ -32,7 +32,8 @@ namespace detail
{
void HandleTryExecuteException(vtkm::cont::DeviceAdapterId deviceId,
vtkm::cont::RuntimeDeviceTracker& tracker)
vtkm::cont::RuntimeDeviceTracker& tracker,
const std::string& functorName)
{
try
{
......@@ -41,44 +42,45 @@ void HandleTryExecuteException(vtkm::cont::DeviceAdapterId deviceId,
}
catch (vtkm::cont::ErrorBadAllocation& e)
{
std::cerr << "caught ErrorBadAllocation " << e.GetMessage() << std::endl;
VTKM_LOG_TRYEXECUTE_DISABLE("Bad allocation (" << e.GetMessage() << ")", functorName, deviceId);
//currently we only consider OOM errors worth disabling a device for
//than we fallback to another device
tracker.ReportAllocationFailure(deviceId, e);
}
catch (vtkm::cont::ErrorBadDevice& e)
{
std::cerr << "caught ErrorBadDevice: " << e.GetMessage() << std::endl;
VTKM_LOG_TRYEXECUTE_DISABLE("Bad device (" << e.GetMessage() << ")", functorName, deviceId);
tracker.ReportBadDeviceFailure(deviceId, e);
}
catch (vtkm::cont::ErrorBadType& e)
{
//should bad type errors should stop the execution, instead of
//deferring to another device adapter?
std::cerr << "caught ErrorBadType : " << e.GetMessage() << std::endl;
VTKM_LOG_TRYEXECUTE_FAIL("ErrorBadType (" << e.GetMessage() << ")", functorName, deviceId);
}
catch (vtkm::cont::ErrorBadValue&)
catch (vtkm::cont::ErrorBadValue& e)
{
// Should bad values be deferred to another device? Seems unlikely they will succeed.
// Re-throw instead.
VTKM_LOG_TRYEXECUTE_FAIL("ErrorBadValue (" << e.GetMessage() << ")", functorName, deviceId);
throw;
}
catch (vtkm::cont::Error& e)
{
VTKM_LOG_TRYEXECUTE_FAIL(e.GetMessage(), functorName, deviceId);
if (e.GetIsDeviceIndependent())
{
// re-throw the exception as it's a device-independent exception.
throw;
}
//general errors should be caught and let us try the next device adapter.
std::cerr << "exception is: " << e.GetMessage() << std::endl;
}
catch (std::exception& e)
{
std::cerr << "caught standard exception: " << e.what() << std::endl;
VTKM_LOG_TRYEXECUTE_FAIL(e.what(), functorName, deviceId);
}
catch (...)
{
VTKM_LOG_TRYEXECUTE_FAIL("Unknown exception", functorName, deviceId);
std::cerr << "unknown exception caught" << std::endl;
}
}
......
......@@ -21,6 +21,7 @@
#define vtk_m_cont_TryExecute_h
#include <vtkm/cont/DeviceAdapterListTag.h>
#include <vtkm/cont/Logging.h>
#include <vtkm/cont/RuntimeDeviceTracker.h>
#include <vtkm/cont/internal/DeviceAdapterTag.h>
......@@ -33,7 +34,8 @@ namespace detail
{
VTKM_CONT_EXPORT void HandleTryExecuteException(vtkm::cont::DeviceAdapterId,
vtkm::cont::RuntimeDeviceTracker&);
vtkm::cont::RuntimeDeviceTracker&,
const std::string& functorName);
template <typename DeviceTag, typename Functor, typename... Args>
inline bool TryExecuteIfValid(std::true_type,
......@@ -51,7 +53,7 @@ inline bool TryExecuteIfValid(std::true_type,
}
catch (...)
{
detail::HandleTryExecuteException(tag, tracker);
detail::HandleTryExecuteException(tag, tracker, vtkm::cont::TypeName<Functor>());
}
}
......
......@@ -31,6 +31,7 @@
#include <vtkm/cont/ArrayPortalToIterators.h>
#include <vtkm/cont/ErrorBadAllocation.h>
#include <vtkm/cont/Logging.h>
#include <vtkm/cont/Storage.h>
//This is in a separate header so that ArrayHandleBasicImpl can include
......@@ -151,6 +152,11 @@ public:
if (static_cast<std::size_t>(numberOfValues) > maxNumVals)
{
VTKM_LOG_F(vtkm::cont::LogLevel::MemExec,
"Refusing to allocate CUDA memory; number of values (%llu) exceeds "
"std::size_t capacity.",
static_cast<vtkm::UInt64>(numberOfValues));
std::ostringstream err;
err << "Failed to allocate " << numberOfValues << " values on device: "
<< "Number of bytes is not representable by std::size_t.";
......@@ -198,6 +204,11 @@ public:
void RetrieveOutputData(StorageType* storage) const
{
storage->Allocate(this->GetNumberOfValues());
VTKM_LOG_F(vtkm::cont::LogLevel::MemTransfer,
"Copying CUDA dev --> host: %s",
vtkm::cont::GetSizeString(this->End - this->Begin).c_str());
try
{
::thrust::copy(thrust::cuda::pointer<ValueType>(this->Begin),
......@@ -250,6 +261,11 @@ private:
try
{
this->PrepareForOutput(this->Storage->GetNumberOfValues());
VTKM_LOG_F(vtkm::cont::LogLevel::MemTransfer,
"Copying host --> CUDA dev: %s.",
vtkm::cont::GetSizeString(this->End - this->Begin).c_str());
::thrust::copy(vtkm::cont::ArrayPortalToIteratorBegin(this->Storage->GetPortalConst()),
vtkm::cont::ArrayPortalToIteratorEnd(this->Storage->GetPortalConst()),
thrust::cuda::pointer<ValueType>(this->Begin));
......
......@@ -20,6 +20,7 @@
#include <cstdlib>
#include <mutex>
#include <vtkm/cont/Logging.h>
#include <vtkm/cont/cuda/ErrorCuda.h>
#include <vtkm/cont/cuda/internal/CudaAllocator.h>
#define NO_VTKM_MANAGED_MEMORY "NO_VTKM_MANAGED_MEMORY"
......@@ -124,6 +125,13 @@ void* CudaAllocator::Allocate(std::size_t numBytes)
VTKM_CUDA_CALL(cudaMalloc(&ptr, numBytes));
}
{
VTKM_LOG_F(vtkm::cont::LogLevel::MemExec,
"Allocated CUDA array of %s at %p.",
vtkm::cont::GetSizeString(numBytes).c_str(),
ptr);
}
return ptr;
}
......@@ -131,11 +139,18 @@ void* CudaAllocator::AllocateUnManaged(std::size_t numBytes)
{
void* ptr = nullptr;
VTKM_CUDA_CALL(cudaMalloc(&ptr, numBytes));
{
VTKM_LOG_F(vtkm::cont::LogLevel::MemExec,
"Allocated CUDA array of %s at %p.",
vtkm::cont::GetSizeString(numBytes).c_str(),
ptr);
}
return ptr;
}
void CudaAllocator::Free(void* ptr)
{
VTKM_LOG_F(vtkm::cont::LogLevel::MemExec, "Freeing CUDA allocation at %p.", ptr);
VTKM_CUDA_CALL(cudaFree(ptr));
}
......@@ -146,6 +161,13 @@ void CudaAllocator::FreeDeferred(void* ptr, std::size_t numBytes)
static std::size_t deferredSize = 0;
constexpr std::size_t bufferLimit = 2 << 24; //16MB buffer
{
VTKM_LOG_F(vtkm::cont::LogLevel::MemExec,
"Deferring free of CUDA allocation at %p of %s.",
ptr,
vtkm::cont::GetSizeString(numBytes).c_str());
}
std::vector<void*> toFree;
// critical section
{
......@@ -161,6 +183,7 @@ void CudaAllocator::FreeDeferred(void* ptr, std::size_t numBytes)
for (auto&& p : toFree)
{
VTKM_LOG_F(vtkm::cont::LogLevel::MemExec, "Freeing deferred CUDA allocation at %p.", p);
VTKM_CUDA_CALL(cudaFree(p));
}
}
......
......@@ -20,6 +20,8 @@
#include <vtkm/cont/cuda/internal/CudaAllocator.h>
#include <vtkm/cont/cuda/internal/ExecutionArrayInterfaceBasicCuda.h>
#include <vtkm/cont/Logging.h>
using vtkm::cont::cuda::internal::CudaAllocator;
namespace vtkm
......@@ -142,6 +144,11 @@ void ExecutionArrayInterfaceBasic<DeviceAdapterTagCuda>::CopyFromControl(
return;
}
VTKM_LOG_F(vtkm::cont::LogLevel::MemTransfer,
"Copying host --> CUDA dev: %s (%llu bytes)",
vtkm::cont::GetHumanReadableSize(numBytes).c_str(),
numBytes);
VTKM_CUDA_CALL(cudaMemcpyAsync(executionPtr,
controlPtr,
static_cast<std::size_t>(numBytes),
......@@ -170,6 +177,11 @@ void ExecutionArrayInterfaceBasic<DeviceAdapterTagCuda>::CopyToControl(const voi
}
else
{
VTKM_LOG_F(vtkm::cont::LogLevel::MemTransfer,
"Copying CUDA dev --> host: %s (%llu bytes)",
vtkm::cont::GetHumanReadableSize(numBytes).c_str(),
numBytes);
VTKM_CUDA_CALL(cudaMemcpyAsync(controlPtr,
executionPtr,
static_cast<std::size_t>(numBytes),
......
<
......@@ -105,6 +105,7 @@
#include <utility>
#include <vtkm/Types.h>
#include <vtkm/cont/Logging.h>
VTKM_THIRDPARTY_PRE_INCLUDE
......@@ -732,6 +733,7 @@ public:
, src_(NULL)
, dst_(NULL)
, out_buf_(NULL)
, tmp_size(0)
{
}
......@@ -770,6 +772,7 @@ private:
ValueType *original_, *tmp_;