Skip to content

[OpenMP][NFC] Modernize the plugin handling #74034

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Dec 1, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 45 additions & 31 deletions openmp/libomptarget/include/PluginManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,23 +20,34 @@

#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/Support/DynamicLibrary.h"

#include <list>
#include <mutex>
#include <string>

struct PluginAdaptorTy {
int32_t Idx = -1; // RTL index, index is the number of devices
// of other RTLs that were registered before,
// i.e. the OpenMP index of the first device
// to be registered with this RTL.
int32_t NumberOfDevices = -1; // Number of devices this RTL deals with.
PluginAdaptorTy(const std::string &Name);

std::unique_ptr<llvm::sys::DynamicLibrary> LibraryHandler;
bool isUsed() const { return DeviceOffset >= 0; }

/// Return the number of devices available to this plugin.
int32_t getNumDevices() const { return NumberOfDevices; }

/// RTL index, index is the number of devices of other RTLs that were
/// registered before, i.e. the OpenMP index of the first device to be
/// registered with this RTL.
int32_t DeviceOffset = -1;

#ifdef OMPTARGET_DEBUG
std::string RTLName;
#endif
/// Number of devices this RTL deals with.
int32_t NumberOfDevices = -1;

/// Name of the shared object file representing the plugin.
std::string Name;

/// Access to the shared object file representing the plugin.
std::unique_ptr<llvm::sys::DynamicLibrary> LibraryHandler;

#define PLUGIN_API_HANDLE(NAME, MANDATORY) \
using NAME##_ty = decltype(__tgt_rtl_##NAME); \
Expand All @@ -45,9 +56,6 @@ struct PluginAdaptorTy {
#include "Shared/PluginAPI.inc"
#undef PLUGIN_API_HANDLE

// Are there images associated with this RTL.
bool IsUsed = false;

llvm::DenseSet<const __tgt_device_image *> UsedImages;

// Mutex for thread-safety when calling RTL interface functions.
Expand All @@ -58,41 +66,26 @@ struct PluginAdaptorTy {

/// RTLs identified in the system.
struct PluginAdaptorManagerTy {
// List of the detected runtime libraries.
std::list<PluginAdaptorTy> AllRTLs;

// Array of pointers to the detected runtime libraries that have compatible
// binaries.
llvm::SmallVector<PluginAdaptorTy *> UsedRTLs;

int64_t RequiresFlags = OMP_REQ_UNDEFINED;

explicit PluginAdaptorManagerTy() = default;

// Register the clauses of the requires directive.
void registerRequires(int64_t Flags);

// Initialize RTL if it has not been initialized
void initRTLonce(PluginAdaptorTy &RTL);

// Initialize all RTLs
void initAllRTLs();

// Register a shared library with all (compatible) RTLs.
void registerLib(__tgt_bin_desc *Desc);

// Unregister a shared library from all RTLs.
void unregisterLib(__tgt_bin_desc *Desc);

// not thread-safe, called from global constructor (i.e. once)
void loadRTLs();

private:
static bool attemptLoadRTL(const std::string &RTLName, PluginAdaptorTy &RTL);
};

/// Struct for the data required to handle plugins
struct PluginManager {
PluginManager() {}

void init();

/// RTLs identified on the host
PluginAdaptorManagerTy RTLs;

Expand Down Expand Up @@ -141,9 +134,30 @@ struct PluginManager {
return Devices.size();
}

int getNumUsedPlugins() const {
int NCI = 0;
for (auto &P : PluginAdaptors)
NCI += P.isUsed();
return NCI;
}

// Initialize \p Plugin if it has not been initialized.
void initPlugin(PluginAdaptorTy &Plugin);

// Initialize all plugins.
void initAllPlugins();

/// Iterator range for all plugin adaptors (in use or not, but always valid).
auto pluginAdaptors() {
return llvm::make_range(PluginAdaptors.begin(), PluginAdaptors.end());
}

private:
bool RTLsLoaded = false;
llvm::SmallVector<__tgt_bin_desc *> DelayedBinDesc;

// List of all plugin adaptors, in use or not.
std::list<PluginAdaptorTy> PluginAdaptors;
};

extern PluginManager *PM;
Expand Down
101 changes: 101 additions & 0 deletions openmp/libomptarget/src/PluginManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,105 @@

#include "PluginManager.h"

using namespace llvm;
using namespace llvm::sys;

PluginManager *PM;

// List of all plugins that can support offloading.
static const char *RTLNames[] = {
/* PowerPC target */ "libomptarget.rtl.ppc64",
/* x86_64 target */ "libomptarget.rtl.x86_64",
/* CUDA target */ "libomptarget.rtl.cuda",
/* AArch64 target */ "libomptarget.rtl.aarch64",
/* AMDGPU target */ "libomptarget.rtl.amdgpu",
};

PluginAdaptorTy::PluginAdaptorTy(const std::string &Name) : Name(Name) {
DP("Attempting to load library '%s'...\n", Name.c_str());

std::string ErrMsg;
LibraryHandler = std::make_unique<DynamicLibrary>(
DynamicLibrary::getPermanentLibrary(Name.c_str(), &ErrMsg));

if (!LibraryHandler->isValid()) {
// Library does not exist or cannot be found.
DP("Unable to load library '%s': %s!\n", Name.c_str(), ErrMsg.c_str());
return;
}

DP("Successfully loaded library '%s'!\n", Name.c_str());

#define PLUGIN_API_HANDLE(NAME, MANDATORY) \
NAME = reinterpret_cast<decltype(NAME)>( \
LibraryHandler->getAddressOfSymbol(GETNAME(__tgt_rtl_##NAME))); \
if (MANDATORY && !NAME) { \
DP("Invalid plugin as necessary interface is not found.\n"); \
return; \
}

#include "Shared/PluginAPI.inc"
#undef PLUGIN_API_HANDLE

// Remove plugin on failure to call optional init_plugin
int32_t Rc = init_plugin();
if (Rc != OFFLOAD_SUCCESS) {
DP("Unable to initialize library '%s': %u!\n", Name.c_str(), Rc);
return;
}

// No devices are supported by this RTL?
NumberOfDevices = number_of_devices();
if (!NumberOfDevices) {
DP("No devices supported in this RTL\n");
return;
}

DP("Registered '%s' with %d devices!\n", Name.c_str(), NumberOfDevices);
}

void PluginManager::init() {
DP("Loading RTLs...\n");

// Attempt to open all the plugins and, if they exist, check if the interface
// is correct and if they are supporting any devices.
for (const char *Name : RTLNames) {
PluginAdaptors.emplace_back(std::string(Name) + ".so");
if (PluginAdaptors.back().getNumDevices() <= 0)
PluginAdaptors.pop_back();
}

DP("RTLs loaded!\n");
}

void PluginManager::initPlugin(PluginAdaptorTy &Plugin) {
// If this RTL is not already in use, initialize it.
if (Plugin.isUsed() || !Plugin.NumberOfDevices)
return;

// Initialize the device information for the RTL we are about to use.
const size_t Start = Devices.size();
Devices.reserve(Start + Plugin.NumberOfDevices);
for (int32_t DeviceId = 0; DeviceId < Plugin.NumberOfDevices; DeviceId++) {
Devices.push_back(std::make_unique<DeviceTy>(&Plugin));
// global device ID
Devices[Start + DeviceId]->DeviceID = Start + DeviceId;
// RTL local device ID
Devices[Start + DeviceId]->RTLDeviceID = DeviceId;
}

// Initialize the index of this RTL and save it in the used RTLs.
Plugin.DeviceOffset = Start;

// If possible, set the device identifier offset in the plugin.
if (Plugin.set_device_offset)
Plugin.set_device_offset(Start);

DP("RTL " DPxMOD " has index %d!\n", DPxPTR(Plugin.LibraryHandler.get()),
Plugin.DeviceOffset);
}

void PluginManager::initAllPlugins() {
for (auto &R : PluginAdaptors)
initPlugin(R);
}
4 changes: 2 additions & 2 deletions openmp/libomptarget/src/interface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ EXTERN void __tgt_register_lib(__tgt_bin_desc *Desc) {

////////////////////////////////////////////////////////////////////////////////
/// Initialize all available devices without registering any image
EXTERN void __tgt_init_all_rtls() { PM->RTLs.initAllRTLs(); }
EXTERN void __tgt_init_all_rtls() { PM->initAllPlugins(); }

////////////////////////////////////////////////////////////////////////////////
/// unloads a target shared library
Expand Down Expand Up @@ -426,7 +426,7 @@ EXTERN void __tgt_push_mapper_component(void *RtMapperHandle, void *Base,
EXTERN void __tgt_set_info_flag(uint32_t NewInfoLevel) {
std::atomic<uint32_t> &InfoLevel = getInfoLevelInternal();
InfoLevel.store(NewInfoLevel);
for (auto &R : PM->RTLs.AllRTLs) {
for (auto &R : PM->pluginAdaptors()) {
if (R.set_info_flag)
R.set_info_flag(NewInfoLevel);
}
Expand Down
2 changes: 1 addition & 1 deletion openmp/libomptarget/src/omptarget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -300,7 +300,7 @@ void handleTargetOutcome(bool Success, ident_t *Loc) {
FAILURE_MESSAGE("Consult https://openmp.llvm.org/design/Runtimes.html "
"for debugging options.\n");

if (PM->RTLs.UsedRTLs.empty()) {
if (!PM->getNumUsedPlugins()) {
llvm::SmallVector<llvm::StringRef> Archs;
llvm::transform(PM->Images, std::back_inserter(Archs),
[](const auto &X) {
Expand Down
Loading