21#ifdef GPUCA_CPUDEVICE_RTC
24#include "GPUReconstructionKernelIncludes.h"
27#include "GPUDefParametersLoad.inc"
28#include "GPUNoFastMathKernels.h"
49static constexpr const char* RTC_SRC_EXTENSION =
".cxx";
50static constexpr const char* RTC_BIN_EXTENSION =
".so";
51static constexpr const char* RTC_MAP_EXTENSION =
".map";
53static bool kernelWithoutRTC(
const std::string&
name) {
return name ==
"GPUTPCCFCheckPadBaseline"; }
55int32_t GPUReconstructionCPUDevice::genRTC(std::string&
filename, uint32_t& nCompile)
57 const std::string_view rtcSource(_binary_GPUReconstructionCPUDevicertc_src_start, _binary_GPUReconstructionCPUDevicertc_src_len);
58 const std::string rtcparam = std::string(
"#define GPUCA_RTC_CODE\n") +
59 std::string(
GetProcessingSettings().rtc.optSpecialCode ?
"#define GPUCA_RTC_SPECIAL_CODE(...) __VA_ARGS__\n" :
"#define GPUCA_RTC_SPECIAL_CODE(...)\n") +
63 filename =
"/tmp/o2cagpu_rtc_cpudevice_";
69 std::vector<std::string> kernels;
70 getRTCKernelCalls(kernels);
71 for (uint32_t
i = 0;
i < kernels.size();
i++) {
76 std::string kernelsall;
77 for (uint32_t
i = 0;
i < kernels.size();
i++) {
78 kernelsall += kernels[
i] +
"\n";
82 baseCommand += (getenv(
"O2_GPU_RTC_OVERRIDE_CMD") ? std::string(getenv(
"O2_GPU_RTC_OVERRIDE_CMD")) :
std::
string(_binary_GPUReconstructionCPUDevicertc_command_start, _binary_GPUReconstructionCPUDevicertc_command_len));
88 throw std::runtime_error(
"Cannot open launch bounds parameter module file");
90 fseek(fp, 0, SEEK_END);
91 size_t size = ftell(fp);
93 throw std::runtime_error(
"launch bounds parameter file has incorrect size");
95 fseek(fp, 0, SEEK_SET);
97 throw std::runtime_error(
"Error reading launch bounds parameter file");
101 const std::string launchBounds = o2::gpu::internal::GPUDefParametersExport(*
mParDevice,
true, 0) +
"#define GPUCA_WARP_SIZE " +
std::to_string(
mWarpSize) +
"\n";
103 GPUInfo(
"RTC Launch Bounds:\n%s", launchBounds.c_str());
111 char shasource[21], shaparam[21], shacmd[21], shakernels[21], shabounds[21], shaversion[21];
113 o2::framework::internal::SHA1(shasource, rtcSource.data(), rtcSource.size());
114 o2::framework::internal::SHA1(shaparam, rtcparam.c_str(), rtcparam.size());
115 o2::framework::internal::SHA1(shacmd, baseCommand.c_str(), baseCommand.size());
116 o2::framework::internal::SHA1(shakernels, kernelsall.c_str(), kernelsall.size());
117 o2::framework::internal::SHA1(shabounds, launchBounds.c_str(), launchBounds.size());
118 o2::framework::internal::SHA1(shaversion, compilerVersions.c_str(), compilerVersions.size());
122 bool cacheLoaded =
false;
130 mode_t
mask = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
133 throw std::runtime_error(
"Error opening rtc cache mutex lock file");
136 if (lockf(fd, F_LOCK, 0)) {
137 throw std::runtime_error(
"Error locking rtc cache mutex file");
141 FILE* fp = fopen(cacheFile.c_str(),
"rb");
146 auto checkSHA = [&](
const char* shacmp,
const char*
name) {
147 if (fread(sharead, 1, 20, fp) != 20) {
148 throw std::runtime_error(
"Cache file corrupt");
151 GPUInfo(
"Cache file content outdated (%s)",
name);
156 if (checkSHA(shasource,
"source") ||
157 checkSHA(shaparam,
"param") ||
158 checkSHA(shacmd,
"command line") ||
159 checkSHA(shakernels,
"kernel definitions") ||
160 checkSHA(shabounds,
"launch bounds") ||
161 checkSHA(shaversion,
"compiler versions")) {
164 GPUSettingsProcessingRTC cachedSettings;
165 static_assert(std::is_trivially_copyable_v<GPUSettingsProcessingRTC> ==
true,
"GPUSettingsProcessingRTC must be POD");
166 if (fread(&cachedSettings,
sizeof(cachedSettings), 1, fp) != 1) {
167 throw std::runtime_error(
"Cache file corrupt");
170 GPUInfo(
"Cache file content outdated (rtc parameters)");
174 for (uint32_t
i = 0;
i < nCompile;
i++) {
175 if (fread(&
len,
sizeof(
len), 1, fp) != 1) {
176 throw std::runtime_error(
"Cache file corrupt");
180 throw std::runtime_error(
"Cache file corrupt");
183 if (fp2 ==
nullptr) {
184 throw std::runtime_error(
"Cannot open tmp file");
187 throw std::runtime_error(
"Error writing file");
191 GPUInfo(
"Using RTC cache file");
200 GPUInfo(
"Starting CPUDevice RTC Compilation");
204 tbb::parallel_for<uint32_t>(0, nCompile, [&](
auto i) {
207 printf(
"Compiling %s\n", (fileBase + RTC_SRC_EXTENSION).c_str());
209 FILE* fp = fopen((fileBase + RTC_SRC_EXTENSION).c_str(),
"w+b");
211 throw std::runtime_error(
"Error opening file");
217 const std::string deterministicStr = std::string(deterministic ?
"#define GPUCA_DETERMINISTIC_CODE(det, indet) det\n" :
"#define GPUCA_DETERMINISTIC_CODE(det, indet) indet\n");
219 if (fwrite(deterministicStr.c_str(), 1, deterministicStr.size(), fp) != deterministicStr.size() ||
220 fwrite(rtcparam.c_str(), 1, rtcparam.size(), fp) != rtcparam.size() ||
221 fwrite(launchBounds.c_str(), 1, launchBounds.size(), fp) != launchBounds.size() ||
222 fwrite(rtcSource.data(), 1, rtcSource.size(), fp) != rtcSource.size() ||
223 fwrite(kernel.c_str(), 1, kernel.size(), fp) != kernel.size()) {
224 throw std::runtime_error(
"Error writing file");
229 fp = fopen((fileBase + RTC_MAP_EXTENSION).c_str(),
"w+b");
230 if (fp ==
nullptr || fprintf(fp,
"{ global: krnl_*; local: *; };\n") < 0) {
231 throw std::runtime_error(
"Error writing version script");
235 std::string command = baseCommand;
237 command += std::string(
" ") + std::string(_binary_GPUReconstructionCPUDevicertc_command_no_fast_math_start, _binary_GPUReconstructionCPUDevicertc_command_no_fast_math_len);
239 command +=
" -Wl,--version-script=" + fileBase + RTC_MAP_EXTENSION +
" -x c++ " + fileBase + RTC_SRC_EXTENSION +
" -o " + fileBase + RTC_BIN_EXTENSION;
241 command +=
" &> /dev/null";
243 command +=
" > /dev/null";
246 printf(
"Running command %s\n", command.c_str());
248 if (system(command.c_str())) {
250 printf(
"Source code file: %s", (fileBase + RTC_SRC_EXTENSION).c_str());
252 throw std::runtime_error(
"Error during CPUDevice RTC compilation");
254 }, tbb::simple_partitioner());
259 FILE* fp = fopen(cacheFile.c_str(),
"w+b");
261 throw std::runtime_error(
"Cannot open cache file for writing");
263 GPUInfo(
"Storing RTC compilation result in cache file");
265 if (fwrite(shasource, 1, 20, fp) != 20 ||
266 fwrite(shaparam, 1, 20, fp) != 20 ||
267 fwrite(shacmd, 1, 20, fp) != 20 ||
268 fwrite(shakernels, 1, 20, fp) != 20 ||
269 fwrite(shabounds, 1, 20, fp) != 20 ||
270 fwrite(shaversion, 1, 20, fp) != 20 ||
272 throw std::runtime_error(
"Error writing cache file");
276 for (uint32_t
i = 0;
i < nCompile;
i++) {
278 if (fp2 ==
nullptr) {
279 throw std::runtime_error(
"Cannot open RTC library file");
281 fseek(fp2, 0, SEEK_END);
282 size_t size = ftell(fp2);
284 fseek(fp2, 0, SEEK_SET);
286 throw std::runtime_error(
"Error reading RTC library file");
290 if (fwrite(&
size,
sizeof(
size), 1, fp) != 1 ||
292 throw std::runtime_error(
"Error writing cache file");
299 if (lockf(fd, F_ULOCK, 0)) {
300 throw std::runtime_error(
"Error unlocking RTC cache mutex file");
308void GPUReconstructionCPUDevice::genAndLoadRTC()
311 uint32_t nCompile = 0;
313 throw std::runtime_error(
"Runtime compilation failed");
315 for (uint32_t
i = 0;
i < nCompile;
i++) {
318 void* lib = dlopen((fileBase + RTC_BIN_EXTENSION).c_str(), RTLD_NOW | RTLD_LOCAL);
319 if (lib ==
nullptr) {
320 throw std::runtime_error(std::string(
"Error loading CPUDevice RTC library: ") + dlerror());
325 remove((fileBase + RTC_SRC_EXTENSION).c_str());
326 remove((fileBase + RTC_BIN_EXTENSION).c_str());
327 remove((fileBase + RTC_MAP_EXTENSION).c_str());
337#define GPUCA_KRNL(x_class, ...) \
338 if (GetKernelNum<GPUCA_M_KRNL_TEMPLATE(x_class)>() != j) { \
339 GPUFatal("kernel numbers out of sync"); \
341 mInternals->rtcKernels[j] = dlsym(mInternals->rtcLibraries[perKernel ? j : 0], GPUCA_M_STR(GPUCA_M_CAT(krnl_, GPUCA_M_KRNL_NAME(x_class)))); \
342 if (mInternals->rtcKernels[j] == nullptr && !kernelWithoutRTC(GetKernelName(j))) { \
343 GPUFatal("Error loading RTC kernel %s", GPUCA_M_STR(GPUCA_M_CAT(krnl_, GPUCA_M_KRNL_NAME(x_class)))); \
346#include "GPUReconstructionKernelList.h"
357int32_t GPUReconstructionCPUDevice::genRTC(std::string&
filename, uint32_t& nCompile)
359 throw std::runtime_error(
"CPUDevice backend compiled without RTC support (requires Linux)");
362void GPUReconstructionCPUDevice::genAndLoadRTC()
364 throw std::runtime_error(
"CPUDevice backend compiled without RTC support (requires Linux)");
double GetCurrentElapsedTime(bool reset=false)
GPUReconstructionCPUDeviceInternals * mInternals
static const char * GetKernelName()
static uint32_t GetNKernels()
GPUDefParameters * mParDevice
static std::string getBackendVersions()
const GPUSettingsProcessing & GetProcessingSettings() const
GLsizei const GLchar *const * string
GLuint const GLchar * name
GLenum GLenum GLsizei len
Polygon< T > close(Polygon< T > polygon)
std::string to_string(gsl::span< T, Size > span)
#define QGET_LD_BINARY_SYMBOLS(filename)
std::vector< void * > rtcLibraries
std::vector< void * > rtcKernels