Project
Loading...
Searching...
No Matches
GPUReconstructionLibrary.cxx
Go to the documentation of this file.
1// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3// All rights not expressly granted are reserved.
4//
5// This software is distributed under the terms of the GNU General Public
6// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7//
8// In applying this license CERN does not waive the privileges and immunities
9// granted to it by virtue of its status as an Intergovernmental Organization
10// or submit itself to any jurisdiction.
11
14
15#ifdef _WIN32
16#include <windows.h>
17#include <winbase.h>
18#include <conio.h>
19#else
20#include <dlfcn.h>
21#include <pthread.h>
22#include <unistd.h>
23#endif
24#include <mutex>
25
26#include "GPUReconstruction.h"
27#include "GPUReconstructionAvailableBackends.h"
28#include "GPUSettings.h"
29
30#include "utils/qlibload.h"
31
32#include "GPULogging.h"
33
34using namespace o2::gpu;
35
37{
39 cfg.deviceType = type;
40 cfg.forceDeviceType = forceType;
41 cfg.master = master;
42 return CreateInstance(cfg);
43}
44
46{
47 GPUReconstruction* retVal = nullptr;
49#ifdef DEBUG_STREAMER
50 if (type != DeviceType::CPU) {
51 GPUError("Cannot create GPUReconstruction for a non-CPU device if DEBUG_STREAMER are enabled");
52 return nullptr;
53 }
54#endif
55 if (type == DeviceType::CPU) {
57 } else {
58 auto* loader = GetLibraryInstance(type, true);
59 if (loader && (retVal = (*loader)->GetPtr(cfg))) {
60 retVal->mMyLib = *loader;
61 }
62 }
63
64 if (retVal == nullptr) {
65 if (cfg.forceDeviceType) {
66 GPUError("Error: Could not load GPUReconstruction for specified device: %s (%u)", gpudatatypes::DEVICE_TYPE_NAMES[type], cfg.deviceType);
67 } else if (type != DeviceType::CPU) {
68 GPUError("Could not load GPUReconstruction for device type %s (%u), falling back to CPU version", gpudatatypes::DEVICE_TYPE_NAMES[type], cfg.deviceType);
69 GPUSettingsDeviceBackend cfg2 = cfg;
70 cfg2.deviceType = DeviceType::CPU;
71 retVal = CreateInstance(cfg2);
72 }
73 } else {
74 GPUInfo("Created GPUReconstruction instance for device type %s (%u)%s", gpudatatypes::DEVICE_TYPE_NAMES[type], cfg.deviceType, cfg.master ? " (slave)" : "");
75 }
76
77 return retVal;
78}
79
81{
82 if (type == DeviceType::CPU) {
83 return true;
84 } else {
85 auto* loader = GetLibraryInstance(type, verbose);
86 return loader != nullptr && (*loader)->LoadLibrary() == 0;
87 }
88}
89
90std::shared_ptr<GPUReconstruction::LibraryLoader>* GPUReconstruction::GetLibraryInstance(DeviceType type, bool verbose)
91{
92 if (type == DeviceType::CPU) {
93 return nullptr;
94 } else if (type == DeviceType::CUDA) {
95#ifdef CUDA_ENABLED
96 return &sLibCUDA;
97#endif
98 } else if (type == DeviceType::HIP) {
99#ifdef HIP_ENABLED
100 return &sLibHIP;
101#endif
102 } else if (type == DeviceType::OCL) {
103#ifdef OPENCL_ENABLED
104 return &sLibOCL;
105#endif
106 } else if (type == DeviceType::METAL) {
107#ifdef METAL_ENABLED
108 return &sLibMETAL;
109#endif
110 } else if (type == DeviceType::CPUDEVICE) {
111#ifdef CPUDEVICE_ENABLED
112 return &sLibCPUDEVICE;
113#endif
114 } else {
115 GPUError("Error: Invalid device type %u", (uint32_t)type);
116 return nullptr;
117 }
118 if (verbose) {
119 GPUInfo("%s Support not compiled in for device type %u (%s)", gpudatatypes::DEVICE_TYPE_NAMES[type], (uint32_t)type, gpudatatypes::DEVICE_TYPE_NAMES[type]);
120 }
121 return nullptr;
122}
123
125{
127 if (t == DeviceType::INVALID_DEVICE) {
128 GPUError("Invalid device type: %s", type);
129 return nullptr;
130 }
131 return CreateInstance(t, forceType, master);
132}
133
134std::shared_ptr<GPUReconstruction::LibraryLoader> GPUReconstruction::sLibCUDA(new GPUReconstruction::LibraryLoader("lib" LIBRARY_PREFIX "GPUTrackingCUDA" LIBRARY_EXTENSION, "GPUReconstruction_Create_CUDA"));
135std::shared_ptr<GPUReconstruction::LibraryLoader> GPUReconstruction::sLibHIP(new GPUReconstruction::LibraryLoader("lib" LIBRARY_PREFIX "GPUTrackingHIP" LIBRARY_EXTENSION, "GPUReconstruction_Create_HIP"));
136std::shared_ptr<GPUReconstruction::LibraryLoader> GPUReconstruction::sLibOCL(new GPUReconstruction::LibraryLoader("lib" LIBRARY_PREFIX "GPUTrackingOCL" LIBRARY_EXTENSION, "GPUReconstruction_Create_OCL"));
137std::shared_ptr<GPUReconstruction::LibraryLoader> GPUReconstruction::sLibMETAL(new GPUReconstruction::LibraryLoader("lib" LIBRARY_PREFIX "GPUTrackingMETAL" LIBRARY_EXTENSION, "GPUReconstruction_Create_METAL"));
138std::shared_ptr<GPUReconstruction::LibraryLoader> GPUReconstruction::sLibCPUDEVICE(new GPUReconstruction::LibraryLoader("lib" LIBRARY_PREFIX "GPUTrackingCPUDevice" LIBRARY_EXTENSION, "GPUReconstruction_Create_CPUDEVICE"));
139
140GPUReconstruction::LibraryLoader::LibraryLoader(const char* lib, const char* func) : mLibName(lib), mFuncName(func), mGPULib(nullptr), mGPUEntry(nullptr) {}
141
143
144int32_t GPUReconstruction::LibraryLoader::LoadLibrary()
145{
146 static std::mutex mut;
147 std::lock_guard<std::mutex> lock(mut);
148
149 if (mGPUEntry) {
150 return 0;
151 }
152
153 LIBRARY_TYPE hGPULib;
154 hGPULib = LIBRARY_LOAD(mLibName);
155 if (hGPULib == nullptr) {
156#ifndef _WIN32
157 GPUImportant("The following error occured during dlopen: %s", dlerror());
158#endif
159 GPUError("Error Opening cagpu library for GPU Tracker (%s)", mLibName);
160 return 1;
161 } else {
162 void* createFunc = LIBRARY_FUNCTION(hGPULib, mFuncName);
163 if (createFunc == nullptr) {
164 GPUError("Error fetching entry function in GPU library\n");
165 LIBRARY_CLOSE(hGPULib);
166 return 1;
167 } else {
168 mGPULib = (void*)(size_t)hGPULib;
169 mGPUEntry = createFunc;
170 GPUInfo("GPU Tracker library loaded and GPU tracker object created sucessfully");
171 }
172 }
173 return 0;
174}
175
176GPUReconstruction* GPUReconstruction::LibraryLoader::GetPtr(const GPUSettingsDeviceBackend& cfg)
177{
178 if (LoadLibrary()) {
179 return nullptr;
180 }
181 if (mGPUEntry == nullptr) {
182 return nullptr;
183 }
184 GPUReconstruction* (*tmp)(const GPUSettingsDeviceBackend& cfg) = (GPUReconstruction * (*)(const GPUSettingsDeviceBackend& cfg)) mGPUEntry;
185 return tmp(cfg);
186}
187
188int32_t GPUReconstruction::LibraryLoader::CloseLibrary()
189{
190 if (mGPUEntry == nullptr) {
191 return 1;
192 }
193 LIBRARY_CLOSE((LIBRARY_TYPE)(size_t)mGPULib);
194 mGPULib = nullptr;
195 mGPUEntry = nullptr;
196 return 0;
197}
198
#define GPUCA_M_STR(a)
int32_t retVal
LibraryLoader(const LibraryLoader &)=delete
static std::shared_ptr< LibraryLoader > sLibHIP
static std::shared_ptr< LibraryLoader > sLibMETAL
static std::shared_ptr< LibraryLoader > * GetLibraryInstance(DeviceType type, bool verbose)
static bool CheckInstanceAvailable(DeviceType type, bool verbose)
static std::shared_ptr< LibraryLoader > sLibOCL
static GPUReconstruction * CreateInstance(const GPUSettingsDeviceBackend &cfg)
static GPUReconstruction * GPUReconstruction_Create_CPU(const GPUSettingsDeviceBackend &cfg)
static std::shared_ptr< LibraryLoader > sLibCPUDEVICE
static std::shared_ptr< LibraryLoader > sLibCUDA
gpudatatypes::DeviceType DeviceType
GLenum func
Definition glcorearb.h:778
GLint GLint GLsizei GLint GLenum GLenum type
Definition glcorearb.h:275
DeviceType GetDeviceType(const char *type)
#define LIBRARY_EXTENSION
Definition qlibload.h:31
#define LIBRARY_CLOSE
Definition qlibload.h:34
#define LIBRARY_TYPE
Definition qlibload.h:32
#define LIBRARY_PREFIX
Definition qlibload.h:39
#define LIBRARY_LOAD(name)
Definition qlibload.h:33
#define LIBRARY_FUNCTION
Definition qlibload.h:35