Skip to content

Commit

Permalink
Add better library load failure messages
Browse files Browse the repository at this point in the history
  • Loading branch information
RyanUnderhill committed Feb 21, 2025
1 parent a207503 commit b3fb7de
Showing 1 changed file with 57 additions and 21 deletions.
78 changes: 57 additions & 21 deletions src/generators.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -128,37 +128,73 @@ struct GenaiInterfaceImpl : GenaiInterface {
void Sequences_RewindTo(Sequences* p_this, size_t new_length) override { return p_this->RewindTo(new_length); }
} g_genai;

DeviceInterface* GetCudaInterface() {
// Load the shared library onnxruntime-genai-cuda.dll
// This is a workaround to avoid linking the CUDA library to the generator library
// The CUDA library is only needed for the CUDA allocator
#if defined(_WIN32)
static std::unique_ptr<void, void (*)(void*)> cuda_library{LoadLibrary((CurrentModulePath() + "onnxruntime-genai-cuda.dll").c_str()),
[](void* h) { FreeLibrary(reinterpret_cast<HMODULE>(h)); }};
struct LibraryHandle {
LibraryHandle(const char* filename) {
auto path = CurrentModulePath() + filename;
handle_ = LoadLibrary(path.c_str());
if (!handle_)
throw std::runtime_error(std::string("Failed to load library: ") + path + " Error: " + std::to_string(GetLastError()));
};

~LibraryHandle() { FreeLibrary(handle_); }

FARPROC __stdcall GetSymbol(const char* name) { return ::GetProcAddress(handle_, name); }

operator HANDLE() { return handle_; }

private:
HMODULE handle_{};
};
#elif defined(__linux__) && !defined(__ANDROID__)
static std::unique_ptr<void, void (*)(void*)> cuda_library{dlopen((Ort::GetCurrentModuleDir() + "/libonnxruntime-genai-cuda.so").c_str(), RTLD_NOW | RTLD_DEEPBIND),
[](void* h) { dlclose(h); }};
struct LibraryHandle {
LibraryHandle(const char* filename) {
auto path = Ort::GetCurrentModuleDir() + "/" + filename;
handle_ = dlopen(path.c_str(), RTLD_NOW | RTLD_LOCAL);
if (!handle_)
throw std::runtime_error(std::string("Failed to load library: ") + path + " Error:" + dlerror());
}
~LibraryHandle() {
dlclose(handle_);
}

void* GetSymbol(const char* name) { return ::dlsym(handle_, name); }

operator void*() { return handle_; }

private:
void* handle_{};
};
#else
static std::unique_ptr<void, void (*)(void*)> cuda_library{nullptr, [](void* h) {}};
#endif
struct LibraryHandle {
LibraryHandle(const char* filename) {}
~LibraryHandle() {}

if (!cuda_library) {
throw std::runtime_error("Cuda interface not available.");
}
void* GetSymbol(const char* name) { return nullptr; }

operator bool() { return false; }
};
#endif

Generators::DeviceInterface* GetInterface(GenaiInterface * p_genai);
static DeviceInterface* cuda_interface{[] {
DeviceInterface* GetCudaInterface() {
try {
#if defined(_WIN32)
auto get_cuda_fn = reinterpret_cast<decltype(&GetInterface)>(GetProcAddress(reinterpret_cast<HMODULE>(cuda_library.get()), "GetInterface"));
static LibraryHandle library{"onnxruntime-genai-cuda.dll"};
#elif defined(__linux__) && !defined(__ANDROID__)
auto get_cuda_fn = reinterpret_cast<decltype(&GetInterface)>(dlsym(cuda_library.get(), "GetInterface"));
static LibraryHandle library{"libonnxruntime-genai-cuda.so"};
#else
auto get_cuda_fn = [](GenaiInterface*) { return nullptr; };
static LibraryHandle library{""};
#endif
return get_cuda_fn(&g_genai);
}()};
if (!library)
throw std::runtime_error("Shared library load failure (see first error)");

return cuda_interface;
Generators::DeviceInterface* GetInterface(GenaiInterface * p_genai);
static DeviceInterface* cuda_interface = reinterpret_cast<decltype(&GetInterface)>(library.GetSymbol("GetInterface"))(&g_genai);

return cuda_interface;
} catch (const std::exception& e) {
throw std::runtime_error("Cuda interface not available: " + std::string(e.what()));
}
}

std::string to_string(DeviceType device_type) {
Expand Down

0 comments on commit b3fb7de

Please sign in to comment.