Project
Loading...
Searching...
No Matches
GPUReconstructionCPUDeviceGenRTC.cxx
Go to the documentation of this file.
1// Copyright 2019-2026 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
16#include "GPULogging.h"
17
18#include <stdexcept>
19#include <string>
20
21#ifdef GPUCA_CPUDEVICE_RTC
22
24#include "GPUReconstructionKernelIncludes.h"
26#include "GPUReconstructionRTCHelpers.inc"
28
29#include <dlfcn.h>
30
31QGET_LD_BINARY_SYMBOLS(GPUReconstructionCPUDevicertc_src);
32QGET_LD_BINARY_SYMBOLS(GPUReconstructionCPUDevicertc_command);
33QGET_LD_BINARY_SYMBOLS(GPUReconstructionCPUDevicertc_command_no_fast_math);
34
35using namespace o2::gpu;
36namespace rtc = o2::gpu::internal::rtc;
37
38static constexpr const char* RTC_SRC_EXTENSION = ".cxx";
39static constexpr const char* RTC_BIN_EXTENSION = ".so";
40static constexpr const char* RTC_MAP_EXTENSION = ".map";
41
42static bool kernelWithoutRTC(const std::string& name) { return name == "GPUTPCCFCheckPadBaseline"; } // Device code requires more than 1 thread per block, use the host-compiled kernel
43
44int32_t GPUReconstructionCPUDevice::genRTC(std::string& filename, uint32_t& nCompile)
45{
46 const auto& proc = GetProcessingSettings();
47 const std::string_view rtcSource(_binary_GPUReconstructionCPUDevicertc_src_start, _binary_GPUReconstructionCPUDevicertc_src_len);
48 const std::string rtcparam = rtc::paramCode(proc, param());
49 rtc::tmpFilename(filename, "/tmp/o2cagpu_rtc_cpudevice_");
50
51 std::vector<std::string> kernels;
52 getRTCKernelCalls(kernels);
53 for (uint32_t i = 0; i < kernels.size(); i++) {
54 if (kernelWithoutRTC(GetKernelName(i))) {
55 kernels[i].clear();
56 }
57 }
58 const std::string kernelsall = rtc::joinKernels(kernels);
59
60 const std::string baseCommand = rtc::baseCommand(proc, std::string_view(_binary_GPUReconstructionCPUDevicertc_command_start, _binary_GPUReconstructionCPUDevicertc_command_len)) + " " + proc.rtctech.overrideArchitecture;
61 const std::string noFastMath(_binary_GPUReconstructionCPUDevicertc_command_no_fast_math_start, _binary_GPUReconstructionCPUDevicertc_command_no_fast_math_len);
62
63 rtc::loadLaunchBounds(proc, *mParDevice);
64 const std::string launchBounds = rtc::launchBoundsCode(proc, *mParDevice, 0, mWarpSize);
65 if (proc.rtctech.printLaunchBounds >= 2) {
66 return 1;
67 }
68
69 nCompile = proc.rtc.compilePerKernel ? kernels.size() : 1;
70 const std::string compilerVersions = getBackendVersions();
71 rtc::Cache cache(proc, "cpudevice", {rtcSource, rtcparam, baseCommand, kernelsall, launchBounds, compilerVersions});
72 if (!cache.load(filename, RTC_BIN_EXTENSION, nCompile)) {
73 rtc::compile(proc, nCompile, "CPUDevice", [&](uint32_t i) {
74 const std::string fileBase = filename + "_" + std::to_string(i);
75 if (proc.debugLevel >= 3) {
76 printf("Compiling %s\n", (fileBase + RTC_SRC_EXTENSION).c_str());
77 }
78 const bool deterministic = rtc::deterministic(proc, GetKernelName(i));
79 rtc::writeSource(fileBase + RTC_SRC_EXTENSION, deterministic, rtcparam, launchBounds, rtcSource, proc.rtc.compilePerKernel ? kernels[i] : kernelsall);
80
81 // Export only the kernel entry points, everything else stays local to the RTC library to avoid symbol collisions
82 FILE* fp = fopen((fileBase + RTC_MAP_EXTENSION).c_str(), "w+b");
83 if (fp == nullptr || fprintf(fp, "{ global: krnl_*; local: *; };\n") < 0) {
84 throw std::runtime_error("Error writing version script");
85 }
86 fclose(fp);
87
88 const std::string command = baseCommand + (deterministic ? " " + noFastMath : "") + " -Wl,--version-script=" + fileBase + RTC_MAP_EXTENSION + " -x c++ " + fileBase + RTC_SRC_EXTENSION + " -o " + fileBase + RTC_BIN_EXTENSION;
89 rtc::runCommand(proc, command, fileBase + RTC_SRC_EXTENSION, "Error during CPUDevice RTC compilation");
90 });
91 cache.store(filename, RTC_BIN_EXTENSION, nCompile);
92 }
93 return 0;
94}
95
96void GPUReconstructionCPUDevice::genAndLoadRTC()
97{
98 std::string filename = "";
99 uint32_t nCompile = 0;
100 if (genRTC(filename, nCompile)) {
101 throw std::runtime_error("Runtime compilation failed");
102 }
103 for (uint32_t i = 0; i < nCompile; i++) {
104 const std::string fileBase = filename + "_" + std::to_string(i);
105 if (GetProcessingSettings().rtctech.runTest != 2) {
106 void* lib = dlopen((fileBase + RTC_BIN_EXTENSION).c_str(), RTLD_NOW | RTLD_LOCAL);
107 if (lib == nullptr) {
108 throw std::runtime_error(std::string("Error loading CPUDevice RTC library: ") + dlerror());
109 }
110 mInternals->rtcLibraries.emplace_back(lib);
111 }
112 if (!GetProcessingSettings().rtctech.keepTempFiles) {
113 remove((fileBase + RTC_SRC_EXTENSION).c_str());
114 remove((fileBase + RTC_BIN_EXTENSION).c_str());
115 remove((fileBase + RTC_MAP_EXTENSION).c_str());
116 }
117 }
118 if (GetProcessingSettings().rtctech.runTest == 2) {
119 return;
120 }
121
122 const bool perKernel = GetProcessingSettings().rtc.compilePerKernel;
124 uint32_t j = 0;
125#define GPUCA_KRNL(x_class, ...) \
126 if (GetKernelNum<GPUCA_M_KRNL_TEMPLATE(x_class)>() != j) { \
127 GPUFatal("kernel numbers out of sync"); \
128 } \
129 mInternals->rtcKernels[j] = dlsym(mInternals->rtcLibraries[perKernel ? j : 0], GPUCA_M_STR(GPUCA_M_CAT(krnl_, GPUCA_M_KRNL_NAME(x_class)))); \
130 if (mInternals->rtcKernels[j] == nullptr && !kernelWithoutRTC(GetKernelName(j))) { \
131 GPUFatal("Error loading RTC kernel %s", GPUCA_M_STR(GPUCA_M_CAT(krnl_, GPUCA_M_KRNL_NAME(x_class)))); \
132 } \
133 j++;
134#include "GPUReconstructionKernelList.h"
135#undef GPUCA_KRNL
136 if (GetProcessingSettings().debugLevel >= 1) {
137 GPUInfo("Loaded %u CPUDevice RTC kernels from %u libraries", j, (uint32_t)mInternals->rtcLibraries.size());
138 }
139}
140
141#else // GPUCA_CPUDEVICE_RTC
142
143using namespace o2::gpu;
144
145int32_t GPUReconstructionCPUDevice::genRTC(std::string& filename, uint32_t& nCompile)
146{
147 throw std::runtime_error("CPUDevice backend compiled without RTC support (requires Linux)");
148}
149
150void GPUReconstructionCPUDevice::genAndLoadRTC()
151{
152 throw std::runtime_error("CPUDevice backend compiled without RTC support (requires Linux)");
153}
154
155#endif // GPUCA_CPUDEVICE_RTC
int32_t i
uint32_t j
Definition RawData.h:0
GPUReconstructionCPUDeviceInternals * mInternals
static const char * GetKernelName()
const GPUSettingsProcessing & GetProcessingSettings() const
GLuint const GLchar * name
Definition glcorearb.h:781
GLenum GLfloat param
Definition glcorearb.h:271
std::string to_string(gsl::span< T, Size > span)
Definition common.h:52
std::string filename()
#define QGET_LD_BINARY_SYMBOLS(filename)