Skip to content

Commit bdafad3

Browse files
authored
Add UNIFIED_BUILDER code for safety samples (NVIDIA#4704) (NVIDIA#4706)
Signed-off-by: Kevin Chen <kevinch@nvidia.com>
1 parent 73b9168 commit bdafad3

File tree

9 files changed

+940
-1
lines changed

9 files changed

+940
-1
lines changed

CMakeLists.txt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,9 @@ if(BUILD_SAFE_SAMPLES OR TRT_SAFETY_INFERENCE_ONLY)
204204
target_link_options(TRTSAFE::nvinfer_safe_shared INTERFACE LINKER:--unresolved-symbols=ignore-in-shared-libs)
205205
target_link_options(TRTSAFE::nvinfer_safe_debug INTERFACE LINKER:--unresolved-symbols=ignore-in-shared-libs)
206206
endif()
207+
208+
# Enable unified builder safety features when building safety samples or in inference-only mode.
209+
add_compile_definitions(ENABLE_UNIFIED_BUILDER=1)
207210
endif()
208211

209212
# OSS safety inference-only mode: require safety samples and disable enterprise
@@ -330,6 +333,15 @@ else()
330333
set(CMAKE_CUDA_RUNTIME_LIBRARY "shared")
331334
endif()
332335

336+
# SafeCUDA (QNX-Safe) does not ship libcudadevrt. When CMAKE_CUDA_RUNTIME_LIBRARY
337+
# is "shared" or "static", CMake automatically links -lcudadevrt for targets with
338+
# CUDA sources, which breaks QNX-Safe cross-compilation. Setting it to "None"
339+
# disables automatic CUDA runtime linking; cudart is still linked manually via
340+
# trt_global_definitions.
341+
if(TRT_SAFETY_INFERENCE_ONLY AND CMAKE_SYSTEM_NAME STREQUAL "QNX")
342+
set(CMAKE_CUDA_RUNTIME_LIBRARY "None")
343+
endif()
344+
333345
find_library(CUDART_LIB ${CUDART_LIB_NAME} HINTS ${CUDA_TOOLKIT_ROOT_DIR} PATH_SUFFIXES lib lib/x64 lib64)
334346
endif()
335347

cmake/toolchains/cmake_qnx_safe.toolchain

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,9 @@ endif()
110110
# We need to set a couple additional flags to compile with SafeCUDA.
111111
# 1. SafeCUDA does not contain cudadevrt, so we need to disable it by setting --cudadevrt=none
112112
# 2. SafeCUDA depends on the QNX Slogger2 library, which must be linked via -lslog2. It is a system library for QNX-Safe.
113-
set(CMAKE_CUDA_FLAGS_INIT "${CMAKE_CUDA_FLAGS_INIT} --cudadevrt=none -lslog2")
113+
# 3. Use --target-directory to tell nvcc to use aarch64-qnx-safe instead of aarch64-qnx
114+
# This is critical to override nvcc's internal _TARGET_DIR_ variable
115+
set(CMAKE_CUDA_FLAGS_INIT "${CMAKE_CUDA_FLAGS_INIT} --cudadevrt=none -lslog2 --target-directory aarch64-qnx-safe")
114116

115117
# We need to explicitly populate `CMAKE_CUDA_FLAGS` with the initial flags so they propagate to the CMake Compiler Identification phase.
116118
# Otherwise, they will only be initialized afterwards, which will cause the identification to fail.

samples/common/sampleEngines.cpp

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,10 @@
3939
#include "sampleOptions.h"
4040
#include "sampleUtils.h"
4141

42+
#if ENABLE_UNIFIED_BUILDER
43+
#include "NvInferConsistency.h"
44+
#include "safeErrorRecorder.h"
45+
#endif
4246

4347
// cspell:ignore calib CUFILE nvonnxparser
4448

@@ -1373,6 +1377,11 @@ bool networkToSerializedEngine(
13731377
if (build.safe && build.consistency)
13741378
{
13751379
std::vector<std::string> pluginBuildLibPaths;
1380+
#if ENABLE_UNIFIED_BUILDER
1381+
pluginBuildLibPaths.reserve(sys.safetyPlugins.size());
1382+
std::transform(sys.safetyPlugins.begin(), sys.safetyPlugins.end(), std::back_inserter(pluginBuildLibPaths),
1383+
[](auto const& sp) { return sp.libraryName; });
1384+
#endif
13761385
if (!checkSafeEngine(serializedEngine->data(), serializedEngine->size(), pluginBuildLibPaths))
13771386
{
13781387
return false;
@@ -1534,6 +1543,11 @@ bool loadEngineToBuildEnv(std::string const& filepath, BuildEnvironment& env, st
15341543
if (enableConsistency)
15351544
{
15361545
std::vector<std::string> pluginBuildLibPaths;
1546+
#if ENABLE_UNIFIED_BUILDER
1547+
pluginBuildLibPaths.reserve(sys.safetyPlugins.size());
1548+
std::transform(sys.safetyPlugins.begin(), sys.safetyPlugins.end(), std::back_inserter(pluginBuildLibPaths),
1549+
[](auto const& sp) { return sp.libraryName; });
1550+
#endif
15371551
if (!checkSafeEngine(engineBlob.data(), fsize, pluginBuildLibPaths))
15381552
{
15391553
sample::gLogError << "Consistency validation is not enabled." << std::endl;
@@ -1987,6 +2001,39 @@ static constexpr auto kCONSISTENCY_CHECKER_LIBRARY = nullptr;
19872001

19882002
} // namespace
19892003

2004+
#if ENABLE_UNIFIED_BUILDER
2005+
2006+
std::unique_ptr<nvinfer2::safe::consistency::IConsistencyChecker> createConsistencyChecker(
2007+
sample::SampleSafeRecorder& recorder, void const* serializedEngine, int32_t const engineSize,
2008+
std::vector<std::string> const& pluginBuildLibPath) noexcept
2009+
{
2010+
2011+
if (serializedEngine == nullptr || engineSize == 0)
2012+
{
2013+
return nullptr;
2014+
}
2015+
2016+
#if !defined(_WIN32)
2017+
if (hasSafeRuntime())
2018+
{
2019+
constexpr char symbolName[] = "createConsistencyChecker";
2020+
using CreateCheckerFn = ErrorCode (*)(nvinfer2::safe::consistency::IConsistencyChecker*& checker,
2021+
sample::SampleSafeRecorder& recorder, void const* data, size_t size,
2022+
std::vector<std::string> const& pluginBuildLibPath);
2023+
if (auto const createFn
2024+
= reinterpret_cast<CreateCheckerFn>(dlsym(kCONSISTENCY_CHECKER_LIBRARY.get(), symbolName)))
2025+
{
2026+
if (nvinfer2::safe::consistency::IConsistencyChecker * checker{nullptr};
2027+
ErrorCode::kSUCCESS == createFn(checker, recorder, serializedEngine, engineSize, pluginBuildLibPath))
2028+
{
2029+
return std::unique_ptr<nvinfer2::safe::consistency::IConsistencyChecker>{checker};
2030+
}
2031+
}
2032+
}
2033+
#endif
2034+
return nullptr;
2035+
}
2036+
#endif
19902037

19912038
bool hasSafeRuntime()
19922039
{
@@ -2001,7 +2048,32 @@ bool hasConsistencyChecker()
20012048
bool checkSafeEngine(
20022049
void const* serializedEngine, int64_t const engineSize, std::vector<std::string> const& pluginBuildLibPath)
20032050
{
2051+
#if !ENABLE_UNIFIED_BUILDER
20042052
return false;
2053+
#else
2054+
if (!hasConsistencyChecker())
2055+
{
2056+
sample::gLogError << "Cannot perform consistency check because the checker is not loaded." << std::endl;
2057+
return false;
2058+
}
2059+
2060+
sample::SampleSafeRecorder recorder{nvinfer2::safe::Severity::kINFO};
2061+
std::unique_ptr<nvinfer2::safe::consistency::IConsistencyChecker> checker
2062+
= createConsistencyChecker(recorder, serializedEngine, engineSize, pluginBuildLibPath);
2063+
if (checker == nullptr)
2064+
{
2065+
sample::gLogError << "Failed to create consistency checker." << std::endl;
2066+
return false;
2067+
}
2068+
sample::gLogInfo << "Start consistency checking." << std::endl;
2069+
if (!checker->validate())
2070+
{
2071+
sample::gLogError << "Consistency validation failed." << std::endl;
2072+
return false;
2073+
}
2074+
sample::gLogInfo << "Consistency validation passed." << std::endl;
2075+
return true;
2076+
#endif
20052077
}
20062078

20072079
} // namespace sample

0 commit comments

Comments
 (0)