Support static builds of nvbench with nvml enabled.

To do this we need to ensure that the nvml init handler is
both contained in the library/executable that uses nvbench.

The original implementation fails since the singleton can be dropped
since it has no usages. So instead we move to a function static
which we ensure will always be used.
This commit is contained in:
Robert Maynard
2023-11-14 14:08:10 -05:00
parent 57c4d42ba5
commit adaef09b20
5 changed files with 55 additions and 42 deletions

View File

@@ -21,6 +21,18 @@ macro(nvbench_generate_exports)
)
endif()
if (TARGET nvbench_json)
set(nvbench_json_code_block
[=[
add_library(nvbench_json INTERFACE IMPORTED)
if (TARGET nlohmann_json::nlohmann_json)
target_link_libraries(nvbench_json INTERFACE nlohmann_json::nlohmann_json)
endif()
]=])
string(APPEND nvbench_build_export_code_block ${nvbench_json_code_block})
string(APPEND nvbench_install_export_code_block ${nvbench_json_code_block})
endif()
rapids_export(BUILD NVBench
EXPORT_SET nvbench-targets
NAMESPACE "nvbench::"

View File

@@ -24,16 +24,14 @@ set(srcs
detail/measure_cold.cu
detail/measure_hot.cu
detail/state_generator.cxx
internal/nvml.cxx
)
if (NVBench_ENABLE_CUPTI)
list(APPEND srcs detail/measure_cupti.cu cupti_profiler.cxx)
endif()
if (NVBench_ENABLE_NVML)
list(APPEND srcs internal/nvml.cxx)
endif()
# CUDA 11.0 can't compile json_printer without crashing
# So for that version fall back to C++ with degraded
# output ( no PTX version info )

View File

@@ -45,6 +45,9 @@ device_info::device_info(int id)
, m_nvml_device(nullptr)
{
NVBENCH_CUDA_CALL(cudaGetDeviceProperties(&m_prop, m_id));
// NVML's lifetime should extend for the entirety of the process, so store in a
// global.
[[maybe_unused]] static auto nvml_lifetime = nvbench::nvml::NVMLLifetimeManager();
#ifdef NVBENCH_HAS_NVML
// Retrieve the current device's pci_id as a null-terminated string.

View File

@@ -32,6 +32,16 @@
namespace nvbench::nvml
{
// RAII struct that initializes and shuts down NVML
// Beeds to be constructed and kept alive while using nvml
struct NVMLLifetimeManager
{
NVMLLifetimeManager();
~NVMLLifetimeManager();
private:
bool m_inited{false};
};
/// Base class for NVML-specific exceptions
struct error : std::runtime_error
{

View File

@@ -16,56 +16,46 @@
* limitations under the License.
*/
#include <nvbench/internal/nvml.cuh>
#include <nvbench/config.cuh>
#include <fmt/format.h>
#include <nvml.h>
#include <nvbench/internal/nvml.cuh>
#include <stdexcept>
namespace
{
#include <fmt/format.h>
#include <nvml.h>
// RAII struct that initializes and shuts down NVML
struct NVMLLifetimeManager
namespace nvbench::nvml
{
NVMLLifetimeManager()
NVMLLifetimeManager::NVMLLifetimeManager()
{
#ifdef NVBENCH_HAS_NVML
try
{
NVBENCH_NVML_CALL_NO_API(nvmlInit());
m_inited = true;
}
catch (std::exception &e)
{
fmt::print("NVML initialization failed:\n {}", e.what());
}
#endif
}
NVMLLifetimeManager::~NVMLLifetimeManager()
{
#ifdef NVBENCH_HAS_NVML
if (m_inited)
{
try
{
NVBENCH_NVML_CALL_NO_API(nvmlInit());
m_inited = true;
NVBENCH_NVML_CALL_NO_API(nvmlShutdown());
}
catch (std::exception &e)
{
fmt::print("NVML initialization failed:\n {}", e.what());
fmt::print("NVML shutdown failed:\n {}", e.what());
}
}
#endif
}
~NVMLLifetimeManager()
{
if (m_inited)
{
try
{
NVBENCH_NVML_CALL_NO_API(nvmlShutdown());
}
catch (std::exception &e)
{
fmt::print("NVML shutdown failed:\n {}", e.what());
}
}
}
private:
bool m_inited{false};
};
// NVML's lifetime should extend for the entirety of the process, so store in a
// global.
auto nvml_lifetime = NVMLLifetimeManager{};
} // namespace
} // namespace nvbench::nvml