Files
project_6/cccl_upstream/c/parallel.v2/src/hostjit/loader.cpp
EngineX CI 56fd68e7dd [INFRA] Import NVIDIA/CCCL upstream as optimization reference library
CCCL (CUDA C++ Core Libraries) provides:
- CUB: device/block/warp-level GPU primitives (reduce, scan, sort, topk)
- Thrust: high-level parallel algorithms (transform_reduce, sort, scan)
- libcudacxx: CUDA C++ standard library (atomics, barriers, memory)
- cudax: experimental features (memory resources, allocators)
- Tuning policies: per-SM hardware-specific algorithm parameters

Competition optimization vectors mapped to CCCL:
- Output TPS (83% weight): warp_reduce, block_reduce, device_topk
- Input TPS (14% weight): device_scan, block_load, prefetch
- Cache TPS (3% weight): prefix caching strategy patterns
- Memory (0.9 util): pooled/cached/buddy allocators

Source: https://github.com/NVIDIA/cccl (shallow clone, HEAD only)
License: Apache-2.0
2026-07-30 09:35:51 +00:00

211 lines
4.8 KiB
C++

#include <hostjit/loader.hpp>
#ifdef _WIN32
# define WIN32_LEAN_AND_MEAN
# include <windows.h>
#else
# include <dlfcn.h>
#endif
namespace hostjit
{
#ifdef _WIN32
namespace
{
// Run C++ static constructors in a DLL loaded with /NOENTRY /NODEFAULTLIB.
// The compiler places CUDA fatbin registration in the .CRT$XCU section.
// Without CRT startup, these never run, so we walk the merged .CRT section
// in the PE and call each non-null function pointer.
void runStaticInitializers(HMODULE module)
{
auto base = reinterpret_cast<const unsigned char*>(module);
auto dos = reinterpret_cast<const IMAGE_DOS_HEADER*>(base);
auto nt = reinterpret_cast<const IMAGE_NT_HEADERS*>(base + dos->e_lfanew);
auto sec = IMAGE_FIRST_SECTION(nt);
for (WORD i = 0; i < nt->FileHeader.NumberOfSections; ++i, ++sec)
{
if (memcmp(sec->Name, ".CRT", 4) == 0)
{
using InitFunc = void(__cdecl*)();
auto funcs = reinterpret_cast<InitFunc*>(const_cast<unsigned char*>(base) + sec->VirtualAddress);
size_t count = sec->SizeOfRawData / sizeof(InitFunc);
for (size_t j = 0; j < count; ++j)
{
if (funcs[j])
{
funcs[j]();
}
}
}
}
}
std::string getWindowsError()
{
DWORD error = GetLastError();
if (error == 0)
{
return "";
}
LPSTR buffer = nullptr;
DWORD size = FormatMessageA(
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
nullptr,
error,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
reinterpret_cast<LPSTR>(&buffer),
0,
nullptr);
std::string message;
if (size > 0 && buffer)
{
message = std::string(buffer, size);
while (!message.empty() && (message.back() == '\n' || message.back() == '\r'))
{
message.pop_back();
}
LocalFree(buffer);
}
else
{
message = "Unknown error (code: " + std::to_string(error) + ")";
}
return message;
}
} // anonymous namespace
#endif
DynamicLibrary::DynamicLibrary()
: handle_(nullptr)
{}
DynamicLibrary::~DynamicLibrary()
{
unload();
}
DynamicLibrary::DynamicLibrary(DynamicLibrary&& other) noexcept
: handle_(other.handle_)
, last_error_(std::move(other.last_error_))
{
other.handle_ = nullptr;
}
DynamicLibrary& DynamicLibrary::operator=(DynamicLibrary&& other) noexcept
{
if (this != &other)
{
unload();
handle_ = other.handle_;
last_error_ = std::move(other.last_error_);
other.handle_ = nullptr;
}
return *this;
}
bool DynamicLibrary::load(const std::string& library_path)
{
unload();
#ifdef _WIN32
SetLastError(0);
handle_ = static_cast<void*>(LoadLibraryA(library_path.c_str()));
if (!handle_)
{
last_error_ = getWindowsError();
if (last_error_.empty())
{
last_error_ = "Unknown LoadLibrary error";
}
return false;
}
// The DLL is linked with /NOENTRY (no CRT startup), so C++ static
// constructors (e.g. CUDA fatbin registration) haven't run yet.
runStaticInitializers(static_cast<HMODULE>(handle_));
#else
dlerror();
handle_ = dlopen(library_path.c_str(), RTLD_LAZY | RTLD_LOCAL);
if (!handle_)
{
const char* error = dlerror();
last_error_ = error ? error : "Unknown dlopen error";
return false;
}
#endif
last_error_.clear();
return true;
}
void* DynamicLibrary::getSymbol(const std::string& symbol_name)
{
if (!handle_)
{
last_error_ = "Library not loaded";
return nullptr;
}
#ifdef _WIN32
SetLastError(0);
void* symbol = reinterpret_cast<void*>(GetProcAddress(static_cast<HMODULE>(handle_), symbol_name.c_str()));
if (!symbol)
{
last_error_ = getWindowsError();
if (last_error_.empty())
{
last_error_ = "Symbol not found: " + symbol_name;
}
return nullptr;
}
#else
dlerror();
void* symbol = dlsym(handle_, symbol_name.c_str());
const char* error = dlerror();
if (error)
{
last_error_ = error;
return nullptr;
}
#endif
last_error_.clear();
return symbol;
}
bool DynamicLibrary::isLoaded() const
{
return handle_ != nullptr;
}
std::string DynamicLibrary::getLastError() const
{
return last_error_;
}
void DynamicLibrary::unload()
{
if (handle_)
{
// Intentionally do NOT unload (dlclose / FreeLibrary) a compiled JIT module. See #9367.
//
// Each JIT .so is built by Clang with the classic fatbin embedding (-fcuda-include-gpubinary),
// which emits a module ctor (__cuda_module_ctor -> __cudaRegisterFatBinary)
// in .init_array but NO matching unregister dtor (.fini_array / __cudaUnregisterFatBinary).
// Unloading such a module unmaps its fatbin while the CUDA runtime still holds a pointer to it;
// that dangling registration corrupts the runtime's module table, so a later module's kernel
// launch silently no-ops.
handle_ = nullptr;
}
last_error_.clear();
}
} // namespace hostjit