27#include "GaudiKernel/Bootstrap.h"
28#include "GaudiKernel/IAppMgrUI.h"
29#include "GaudiKernel/IAlgManager.h"
30#include "GaudiKernel/IAlgorithm.h"
31#include "GaudiKernel/ISvcLocator.h"
32#include "GaudiKernel/SmartIF.h"
33#include "GaudiKernel/StateMachine.h"
42 void promoteSelfToGlobal() {
44 if (!dladdr(
reinterpret_cast<void*
>(&promoteSelfToGlobal), &info) ||
46 throw std::runtime_error(
47 "TracccTritonInitializer: dladdr() could not determine this "
48 "library's own path");
50 if (!dlopen(
info.dli_fname, RTLD_NOW | RTLD_GLOBAL | RTLD_NOLOAD)) {
51 throw std::runtime_error(
52 std::string(
"TracccTritonInitializer: failed to promote '") +
53 info.dli_fname +
"' to RTLD_GLOBAL: " + dlerror());
60 SmartIF<IAppMgrUI>
app;
68 SmartIF<IAlgorithm>
algorithm(
const std::string& name)
const {
69 IAlgManager* algMgr =
svcLocator.as<IAlgManager>();
71 throw std::runtime_error(
72 "TracccTritonInitializer: no IAlgManager available");
74 SmartIF<IAlgorithm> alg = algMgr->algorithm(name,
false);
76 throw std::runtime_error(
77 "TracccTritonInitializer: could not retrieve algorithm '" +
78 name +
"' from the embedded Athena application");
86 PyObject* item = PyDict_GetItemString(dict, name);
87 if (!item || !PyUnicode_Check(item)) {
88 throw std::runtime_error(
89 std::string(
"TracccTritonInitializer: TracccTritonBootstrap."
90 "bootstrap() returned no string entry '") + name +
91 "' in its StoreGate key dictionary");
93 const char* value = PyUnicode_AsUTF8(item);
94 if (!value || !*value) {
95 throw std::runtime_error(
96 std::string(
"TracccTritonInitializer: empty StoreGate key '") +
97 name +
"' returned by TracccTritonBootstrap.bootstrap()");
105 const std::size_t nSlots =
config.nSlots;
106 const std::string& sequenceName =
config.sequenceName;
107 if (!Py_IsInitialized()) {
108 if (!dlopen(TRACCC_TRITON_PYTHON_LIBRARY, RTLD_NOW | RTLD_GLOBAL)) {
109 throw std::runtime_error(
111 "TracccTritonInitializer: failed to re-load '"
112 TRACCC_TRITON_PYTHON_LIBRARY
"' with RTLD_GLOBAL: ") +
117 if (!Py_IsInitialized()) {
118 throw std::runtime_error(
119 "TracccTritonInitializer: Py_Initialize() failed");
124 PyImport_ImportModule(
"TracccTritonBackend.TracccTritonBootstrap");
127 throw std::runtime_error(
128 "TracccTritonInitializer: failed to import "
129 "TracccTritonBackend.TracccTritonBootstrap -- check "
133 PyObject* func = PyObject_GetAttrString(module,
"bootstrap");
135 if (!func || !PyCallable_Check(func)) {
138 throw std::runtime_error(
139 "TracccTritonInitializer: TracccTritonBootstrap.bootstrap "
140 "not found or not callable");
144 PyObject_CallFunction(func,
"ns",
static_cast<Py_ssize_t
>(nSlots),
145 sequenceName.c_str());
149 throw std::runtime_error(
150 "TracccTritonInitializer: TracccTritonBootstrap.bootstrap() "
151 "raised a Python exception (see stderr above)");
153 if (!PyDict_Check(result)) {
155 throw std::runtime_error(
156 "TracccTritonInitializer: TracccTritonBootstrap.bootstrap() "
157 "did not return a dictionary of StoreGate keys");
193 static std::mutex initMutex;
194 std::lock_guard<std::mutex>
lock(initMutex);
200 throw std::runtime_error(
201 "TracccTritonInitializer: already initialized on device " +
202 std::to_string(
m_impl->config.deviceId) +
203 ", cannot re-initialize on device " +
204 std::to_string(
config.deviceId) +
205 ". Pin the model to a single GPU in instance_group.");
208 throw std::runtime_error(
209 "TracccTritonInitializer: already initialized with " +
210 std::to_string(
m_impl->config.nSlots) +
211 " event slots, cannot re-initialize with " +
212 std::to_string(
config.nSlots));
219 promoteSelfToGlobal();
222 m_impl->bootstrapPython();
225 m_impl->app = Gaudi::createApplicationMgr();
227 throw std::runtime_error(
228 "TracccTritonInitializer: Gaudi::createApplicationMgr() "
229 "returned null after the Python bootstrap");
232 if (
m_impl->app->FSMState() != Gaudi::StateMachine::RUNNING) {
233 throw std::runtime_error(
234 "TracccTritonInitializer: application manager is not "
235 "RUNNING after the Python bootstrap (FSM state " +
236 std::to_string(
static_cast<int>(
m_impl->app->FSMState())) +
")");
240 if (!
m_impl->svcLocator) {
241 throw std::runtime_error(
242 "TracccTritonInitializer: could not obtain ISvcLocator");
252 if (!
m_impl->ready)
return;
257 m_impl->app->stop().ignore();
258 m_impl->app->finalize().ignore();
259 m_impl->app->terminate().ignore();
262 m_impl->svcLocator =
nullptr;
279 throw std::runtime_error(
280 "TracccTritonInitializer::acquireSlot: not initialized");
282 const std::size_t slot =
m_impl->nextSlot.fetch_add(1);
283 if (slot >=
m_impl->config.nSlots) {
284 throw std::runtime_error(
285 "TracccTritonInitializer: Triton created more model instances "
286 "than the " + std::to_string(
m_impl->config.nSlots) +
287 " event slot(s) the application was configured with");
293 return m_impl->config.deviceId;
297 if (!
m_impl->svcLocator) {
298 throw std::runtime_error(
299 "TracccTritonInitializer::serviceLocator: not initialized");
301 return *
m_impl->svcLocator;
virtual void lock()=0
Interface to allow an object to lock itself when made const in SG.
Initialization of GPU tracking algs. for use in Triton as-a-Service implementation.
Define macros for attributes used to control the static checker.
#define ATLAS_THREAD_SAFE
static TracccTritonInitializer & instance()
Get the process-wide singleton.
std::size_t acquireSlot()
Claim the next free event-store slot for a Triton model instance.
bool isReady() const
Whether initialize has completed successfully.
ISvcLocator & serviceLocator() const
The service locator of the embedded Athena application (never null once ready).
TracccTritonInitializer(const TracccTritonInitializer &)=delete
~TracccTritonInitializer()
std::unique_ptr< Impl > m_impl
void initialize(const Config &config)
Boot the embedded Athena application and resolve all cached handles.
const Config & config() const
The construction parameters the application was configured with.
void finalize()
Tear the application down. Safe to call when not initialized.
TracccTritonInitializer()
int deviceId() const
The CUDA device id this instance is pinned to.
Construction parameters, normally read from the model config, plus the StoreGate keys initialize() fi...
static std::string keyFromDict(PyObject *dict, const char *name)
Read one string entry out of the dictionary bootstrap() returned.
SmartIF< IAlgorithm > algorithm(const std::string &name) const
Look up an algorithm (or sequence) by the name it was created under.
void bootstrapPython()
Embed a Python interpreter and call TracccTritonBackend.TracccTritonBootstrap.bootstrap().
SmartIF< ISvcLocator > svcLocator
std::atomic< std::size_t > nextSlot
Next event-store slot to hand out; see acquireSlot().
PyThreadState * pyMainThreadState