ATLAS Offline Software
DeviceMgmtSvc.cxx
Go to the documentation of this file.
1 //
2 // Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
3 //
4 
5 // Local include(s).
6 #include "DeviceMgmtSvc.h"
7 
8 // System include(s).
9 #include <filesystem>
10 #include <fstream>
11 
12 namespace AthXRT {
13 
19 
20  std::vector<cl::Platform> platforms;
21 
22  ATH_CHECK(cl::Platform::get(&platforms) == CL_SUCCESS);
23  si.device_count = 0;
24  for (const cl::Platform &platform : platforms) {
25 
26  // Filter platforms by name. Currently AMD FPGA platform is
27  // still referenced as "Xilinx".
28  std::string platform_name;
29  ATH_CHECK(platform.getInfo(CL_PLATFORM_NAME, &platform_name) == CL_SUCCESS);
30  if (platform_name != "Xilinx") {
31  ATH_MSG_WARNING("Skipping unsuported platform " << platform_name);
32  continue;
33  }
34 
35  // Get devices list for the platform and count total devices.
36  std::vector<cl::Device> devices;
37  ATH_CHECK(platform.getDevices(CL_DEVICE_TYPE_ACCELERATOR, &devices) ==
38  CL_SUCCESS);
39  ATH_MSG_DEBUG("Found XRT/OpenCL platform '" << platform_name << "' with "
40  << devices.size()
41  << " devices");
42  si.device_count += devices.size();
43 
44  // Group devices by type, using the name property.
45  // All similar devices should have the same name,
46  // I.E: "xilinx_u250_gen3x16_xdma_shell_4_1"
47  for (const cl::Device &device : devices) {
48  const std::string device_name = get_device_name(device);
49 
50  // Check if we already have a device with the same name.
51  bool found = false;
52  for (std::vector<cl::Device> &list : si.device_types) {
53  std::string list_device_name;
54  ATH_CHECK(list[0].getInfo(CL_DEVICE_NAME, &list_device_name) ==
55  CL_SUCCESS);
56  if (device_name == list_device_name) {
57  found = true;
58  list.push_back(device);
59  break;
60  }
61  }
62  if (!found) {
63  std::vector<cl::Device> new_list = {device};
64  si.device_types.push_back(new_list);
65  }
66  }
67  }
68 
69  // We expect to have at least one device to program.
70  if (si.device_count < 1) {
71  // This should not be this catastrophic and we could fallback to
72  // software implementation, but for now we will consider that an
73  // accelerator have to be present if this service is configured.
74  ATH_MSG_ERROR("No XRT device found");
75  return StatusCode::FAILURE;
76  } else {
77  ATH_MSG_INFO("Found a total of "
78  << si.device_count << " AMD FPGA device(s) ("
79  << si.device_types.size() << " device type(s))");
80  }
81 
82  return StatusCode::SUCCESS;
83 
84 } // DeviceMgmtSvc::inspect_devices()
85 
91 
92  // We expect at least one XCLBIN file to be specified.
93  if (m_xclbin_path_list.empty()) {
94  ATH_MSG_ERROR("No XCLBIN list specified");
95  return StatusCode::FAILURE;
96  }
97 
98  // If there is more XCLBIN files to program than device(s), this
99  // is probably an error (the opposite is ok).
100  if (m_xclbin_path_list.size() > si.device_count) {
102  "More XCLBIN file(s) specified than "
103  "devices type available ("
104  << si.device_count << "): ");
105  for (const std::string &xclbin_path : m_xclbin_path_list) {
106  ATH_MSG_ERROR(xclbin_path);
107  }
108  return StatusCode::FAILURE;
109  }
110 
111  // Inspect XCLBIN files.
112  for (const std::string &xclbin_path : m_xclbin_path_list) {
113 
114  if (!std::filesystem::exists(xclbin_path)) {
115  ATH_MSG_ERROR("XCLBIN file does not exist: " << xclbin_path);
116  return StatusCode::FAILURE;
117  }
118 
119  // Create a temporary XRT API XCLBIN object to use introspection
120  // to gather some information. With this approach, we are loading
121  // them twice from disk which is not optimal.
122  DeviceMgmtSvc::XclbinInfo xclbin_info;
123  try {
124  xrt::xclbin xrt_xclbin(xclbin_path);
125  xclbin_info.path = xclbin_path;
126  xclbin_info.xsa_name = xrt_xclbin.get_xsa_name();
127  xclbin_info.fpga_device_name = xrt_xclbin.get_fpga_device_name();
128  xclbin_info.uuid = xrt_xclbin.get_uuid().to_string();
129  for (const xrt::xclbin::kernel &kernel : xrt_xclbin.get_kernels()) {
130  // Ensure that the kernel have a least one compute unit.
131  // Having a kernel without compute unit is not a common use case,
132  // but it is possible if a .xo with a kernel is linked in the
133  // .xclbin, but the number of said kernel is set to 0.
134  if (!kernel.get_cus().empty()) {
135  xclbin_info.kernel_names.push_back(kernel.get_name());
136  }
137  }
138  } catch (...) {
139  ATH_MSG_ERROR("Could not create xrt::xclbin from " << xclbin_path);
140  return StatusCode::FAILURE;
141  }
142  m_xclbin_infos.push_back(xclbin_info);
143  }
144 
145  // Extract some more information from the XCLBIN collection:
146  // The number of different XCLBIN files and the number of different
147  // FPGA device names targeted by the XCLBIN files.
148  std::set<std::string> uuids;
149  std::set<std::string> fpga_device_names;
150  for (const XclbinInfo &info : m_xclbin_infos) {
151  uuids.insert(info.uuid);
152  fpga_device_names.insert(info.fpga_device_name);
153  }
154  si.different_xclbin_count = uuids.size();
155  si.different_xclbin_fpga_device_name = fpga_device_names.size();
156 
157  return StatusCode::SUCCESS;
158 
159 } // DeviceMgmtSvc::inspect_xclbin()
160 
164 std::string DeviceMgmtSvc::get_device_name(const cl::Device &device) const {
165 
166  cl_int err = CL_SUCCESS;
167  std::string device_name;
168  err = device.getInfo(CL_DEVICE_NAME, &device_name);
169  if (err != CL_SUCCESS) {
170  ATH_MSG_ERROR("Failed to get device name");
171  return std::string("error");
172  }
173  return device_name;
174 }
175 
179 std::string DeviceMgmtSvc::get_device_bdf(const cl::Device &device) const {
180 
181  cl_int err = CL_SUCCESS;
182  std::string device_bdf;
183  err = device.getInfo(CL_DEVICE_PCIE_BDF, &device_bdf);
184  if (err != CL_SUCCESS) {
185  ATH_MSG_ERROR("Failed to get device BDF");
186  return std::string("error");
187  }
188  return device_bdf;
189 }
190 
197 static std::string getPrefixUpToNthOccurrence(const std::string &str,
198  char token, int n) {
199 
200  std::size_t pos = 0;
201  int count = 0;
202 
203  // Iterate through the string to find the nth occurrence of the token
204  while (count < n && pos != std::string::npos) {
205  pos = str.find(token, pos + 1);
206  count++;
207  }
208 
209  // If the token isn't found n times, return the whole string
210  if (pos == std::string::npos) {
211  return str;
212  }
213 
214  // Return the substring up to and including the nth occurrence
215  return str.substr(0, pos + 1);
216 }
217 
227  const DeviceMgmtSvc::XclbinInfo &xclbin_info,
228  const cl::Device &device) const {
229 
230  const std::string device_prefix =
231  getPrefixUpToNthOccurrence(get_device_name(device), '_', 2);
232  const std::string xsa_prefix =
233  getPrefixUpToNthOccurrence(xclbin_info.xsa_name, '_', 2);
234  if (device_prefix == xsa_prefix) {
235  return true;
236  } else {
237  return false;
238  }
239 }
240 
262 
263  // Do we have only one FPGA type?
264  if (si.device_types.size() == 1) {
265 
266  if (m_xclbin_infos.size() == 1) {
267 
268  // We have one or multiple device(s) of the same type and only have one
269  // XCLBIN: Program all device(s) with the same XCLBIN and create one
270  // context.
271  ATH_MSG_DEBUG("Case 1: One or multiple identical device(s), one xclbin");
272  DeviceMgmtSvc::AthClContext ath_cl_context;
273  for (const cl::Device &device : si.device_types[0]) {
274  ath_cl_context.devices.push_back(device);
275  }
276  ath_cl_context.xclbin_info = m_xclbin_infos[0];
277  m_ath_cl_contexts.push_back(ath_cl_context);
278 
279  } else {
280 
282 
283  // This is an error: we only have one FPGA type but
284  // XCLBIN files targeting multiple fpga.
286  "Specified XCLBINs target multiple device types, but only one "
287  "device type is present");
288  return StatusCode::FAILURE;
289  }
290 
291  if (si.different_xclbin_count == 1) {
292  // We have multiple device of the same type and multiple identical
293  // xclbin: Program the same number of devices that we have XCLBIN files,
294  // but put them in only one context as the XCLBIN will be identical for
295  // all programmed devices. Some devices might be left un-programmed.
297  "Case 2: Multiple identical devices, multiple identical xclbins");
298  DeviceMgmtSvc::AthClContext ath_cl_context;
299  for (std::size_t i = 0; i < m_xclbin_infos.size(); ++i) {
300  ath_cl_context.devices.push_back(si.device_types[0][i]);
301  }
302  ath_cl_context.xclbin_info = m_xclbin_infos[0];
303  m_ath_cl_contexts.push_back(ath_cl_context);
304 
305  } else {
306 
307  // We have multiple device of the same type and multiple different
308  // XCLBIN, but all targeting the same device: Program all devices with a
309  // differnt XCLBIN and create one context per device/XCLBIN. Some
310  // devices might be left un-programmed.
312  "Case 3: Multiple identical devices, multiple different XCLBIN "
313  "files, but targeting the same device type");
314  for (std::size_t i = 0; i < m_xclbin_infos.size(); ++i) {
315  DeviceMgmtSvc::AthClContext ath_cl_context;
316  ath_cl_context.xclbin_info = m_xclbin_infos[i];
317  ath_cl_context.devices.push_back(si.device_types[0][i]);
318  m_ath_cl_contexts.push_back(ath_cl_context);
319  }
320  }
321  }
322  } else {
323 
324  // More tricky (and probably an edge case): we have different
325  // devices types. We will try to pair each device them with a
326  // XCLBIN files based on the device name and XCLBIN XSA name,
327  // and load them in separate contexts.
328  ATH_MSG_DEBUG("Case 4: Multiple different devices, multiple xclbins");
329  std::vector<XclbinInfo> unaffected_xclbin_infos(m_xclbin_infos);
330  for (const std::vector<cl::Device> &device_type : si.device_types) {
331  for (const cl::Device &device : device_type) {
332  DeviceMgmtSvc::AthClContext ath_cl_context;
333  ath_cl_context.devices.push_back(device);
334 
335  // Try to find a matching XCLBIN for this device.
337  bool found = false;
338  for (iter = unaffected_xclbin_infos.begin();
339  iter != unaffected_xclbin_infos.end();) {
340  if (is_xclbin_compatible_with_device(*iter, device)) {
341  ath_cl_context.xclbin_info = *iter;
342  iter = unaffected_xclbin_infos.erase(iter);
343  found = true;
344  break;
345  } else {
346  ++iter;
347  }
348  }
349 
350  // Only keep this combination if we found a matching XCLBIN.
351  if (found) {
352  m_ath_cl_contexts.push_back(ath_cl_context);
353  } else {
354  // If we did not find a matching XCLBIN, we will not program the
355  // device. This is not an error, but we will report it.
356  ATH_MSG_WARNING("No compatible XCLBIN found for device "
357  << get_device_name(device) << " ("
358  << get_device_bdf(device) << ")");
359  }
360  }
361  }
362 
363  for (const XclbinInfo &xclbin_info : unaffected_xclbin_infos) {
364  // Report XCLBIN files that were not affected to a device.
365  // (This could happen for XCLBIN not compatible with any device.)
367  "No compatible device found for XCLBIN: " << xclbin_info.path);
368  }
369  }
370 
371  return StatusCode::SUCCESS;
372 
373 } // DeviceMgmtSvc::pair_devices_and_xclbins()
374 
382 
383  cl_int err = CL_SUCCESS;
384 
385  for (AthClContext &ath_cl_context : m_ath_cl_contexts) {
386 
387  // Create an OpenCL context for the device(s).
388  ath_cl_context.context = std::make_shared<cl::Context>(
389  ath_cl_context.devices, nullptr, nullptr, nullptr, &err);
390  if (err != CL_SUCCESS) {
391  ATH_MSG_ERROR("Failed to create cl::Context");
392  return StatusCode::FAILURE;
393  }
394 
395  // Load XCLBIN file from disk.
396  std::ifstream file;
397  try {
398  file.open(ath_cl_context.xclbin_info.path.c_str(), std::ios::binary);
399  } catch (...) {
400  ATH_MSG_ERROR("Could not open " << ath_cl_context.xclbin_info.path
401  << " for reading");
402  return StatusCode::FAILURE;
403  }
404  std::vector<char> xclbin_buffer((std::istreambuf_iterator<char>(file)),
405  std::istreambuf_iterator<char>());
406 
407  // Wrap XCLBIN data and size in a vector of cl::Program::Binaries.
408  // If we program multiple devices, we need to provide the same
409  // binary for each device.
410  cl::Program::Binaries binary;
411  for (std::size_t i = 0; i < ath_cl_context.devices.size(); ++i) {
412  binary.push_back({xclbin_buffer.data(), xclbin_buffer.size()});
413  }
414 
415  // Create a program from the XCLBIN binary.
416  // Effectively loading the XCLBIN on the device(s).
417  ath_cl_context.program = std::make_shared<cl::Program>(
418  *ath_cl_context.context, ath_cl_context.devices, binary, nullptr, &err);
419  if (err != CL_SUCCESS) {
420  ATH_MSG_ERROR("Failed to create cl::Program");
421  return StatusCode::FAILURE;
422  }
423 
424  // Report what have been done.
425  std::string bdfs = "";
426  for (const cl::Device &device : ath_cl_context.devices) {
427  bdfs += get_device_bdf(device);
428  bdfs += " ";
429  }
430  ATH_MSG_INFO("Loaded " << ath_cl_context.xclbin_info.path << " on "
431  << ath_cl_context.devices.size() << " "
432  << get_device_name(ath_cl_context.devices[0])
433  << " device(s): " << bdfs);
434  }
435 
436  return StatusCode::SUCCESS;
437 
438 } // DeviceMgmtSvc::program_devices
439 
447 
448  SystemInfo sys_info;
449 
450  // Inspect available device(s) and fill sys_info.
451  ATH_CHECK(inspect_devices(sys_info));
452 
453  // Inspect provided XCLBINs to gather information about kernel(s)
454  // into sys_info and a list of XclbinInfo.
455  ATH_CHECK(inspect_xclbins(sys_info));
456 
457  // Now we can make a decision about the pairing of device(s)
458  // and xclbin(s), and the number of required context(s) by
459  // filling m_ath_cl_contexts.
461 
462  // Program the devices with the XCLBINs and create contexts,
463  // and programs based on m_ath_cl_contexts.
465 
466  // Return gracefully.
467  return StatusCode::SUCCESS;
468 }
469 
471 
472  // Finalise the base class.
474 
475  // Return gracefully.
476  return StatusCode::SUCCESS;
477 }
478 
479 const std::vector<std::shared_ptr<xrt::device>>
481 
482  std::vector<std::shared_ptr<xrt::device>> devices;
483 
484  // Iterate over all contexts and check if the kernel name is in the list.
485  // If so, add the device(s) to the list of devices to return.
486  for (const AthClContext &ath_cl_context : m_ath_cl_contexts) {
487  if (std::find(ath_cl_context.xclbin_info.kernel_names.begin(),
488  ath_cl_context.xclbin_info.kernel_names.end(),
489  name) != ath_cl_context.xclbin_info.kernel_names.end()) {
490  for (const cl::Device &device : ath_cl_context.devices) {
491  devices.push_back(std::make_shared<xrt::device>(
492  xrt::opencl::get_xrt_device(device())));
493  }
494  }
495  }
496 
497  return devices;
498 }
499 
500 const std::vector<IDeviceMgmtSvc::OpenCLHandle>
502  const std::string &name) const {
503 
504  std::vector<IDeviceMgmtSvc::OpenCLHandle> handles;
505 
506  // Iterate over all contexts and check if the kernel name is in the list.
507  // If so, add the context and program to the list of handles to return.
508  for (const AthClContext &ath_cl_context : m_ath_cl_contexts) {
509  if (std::find(ath_cl_context.xclbin_info.kernel_names.begin(),
510  ath_cl_context.xclbin_info.kernel_names.end(),
511  name) != ath_cl_context.xclbin_info.kernel_names.end()) {
512  IDeviceMgmtSvc::OpenCLHandle handle = {ath_cl_context.context,
513  ath_cl_context.program};
514  handles.push_back(handle);
515  }
516  }
517 
518  return handles;
519 }
520 
521 } // namespace AthXRT
grepfile.info
info
Definition: grepfile.py:38
xAOD::iterator
JetConstituentVector::iterator iterator
Definition: JetConstituentVector.cxx:68
AthXRT::DeviceMgmtSvc::get_opencl_handles_by_kernel_name
virtual const std::vector< IDeviceMgmtSvc::OpenCLHandle > get_opencl_handles_by_kernel_name(const std::string &name) const override
Get a list of OpenCL handles providing the specified kernel.
Definition: DeviceMgmtSvc.cxx:501
AthXRT::DeviceMgmtSvc::finalize
virtual StatusCode finalize() override
Finalise the service.
Definition: DeviceMgmtSvc.cxx:470
AthXRT::DeviceMgmtSvc::SystemInfo::different_xclbin_count
std::size_t different_xclbin_count
Definition: DeviceMgmtSvc.h:93
AthXRT::DeviceMgmtSvc::XclbinInfo::kernel_names
std::vector< std::string > kernel_names
Definition: DeviceMgmtSvc.h:116
python.tests.PyTestsLib.finalize
def finalize(self)
_info( "content of StoreGate..." ) self.sg.dump()
Definition: PyTestsLib.py:50
AthXRT::DeviceMgmtSvc::AthClContext
Struct to hold information about a context, as well as the devices, the program and XCLBIN file assoc...
Definition: DeviceMgmtSvc.h:129
AthXRT::DeviceMgmtSvc::m_xclbin_infos
std::vector< XclbinInfo > m_xclbin_infos
List of XCLBIN files info configured for the service.
Definition: DeviceMgmtSvc.h:125
AthXRT::DeviceMgmtSvc::SystemInfo::different_xclbin_fpga_device_name
std::size_t different_xclbin_fpga_device_name
Definition: DeviceMgmtSvc.h:94
ATH_MSG_INFO
#define ATH_MSG_INFO(x)
Definition: AthMsgStreamMacros.h:31
find
std::string find(const std::string &s)
return a remapped string
Definition: hcg.cxx:135
AthXRT::DeviceMgmtSvc::get_xrt_devices_by_kernel_name
virtual const std::vector< std::shared_ptr< xrt::device > > get_xrt_devices_by_kernel_name(const std::string &name) const override
Get a list of XRT devices providing the specified kernel.
Definition: DeviceMgmtSvc.cxx:480
AthXRT::IDeviceMgmtSvc::OpenCLHandle::context
std::shared_ptr< cl::Context > context
Definition: IDeviceMgmtSvc.h:49
AthXRT::DeviceMgmtSvc::SystemInfo
Definition: DeviceMgmtSvc.h:86
AthXRT::DeviceMgmtSvc::get_device_bdf
std::string get_device_bdf(const cl::Device &device) const
Get the BDF (bus:device:function) string of a cl::device.
Definition: DeviceMgmtSvc.cxx:179
AthXRT::DeviceMgmtSvc::XclbinInfo::path
std::string path
Definition: DeviceMgmtSvc.h:112
AthXRT::DeviceMgmtSvc::inspect_xclbins
StatusCode inspect_xclbins(SystemInfo &si)
Inspect the provided XCLBIN files and fill the SystemInfo structure.
Definition: DeviceMgmtSvc.cxx:90
AthXRT::DeviceMgmtSvc::XclbinInfo::fpga_device_name
std::string fpga_device_name
Definition: DeviceMgmtSvc.h:114
AthXRT::DeviceMgmtSvc::AthClContext::xclbin_info
XclbinInfo xclbin_info
Definition: DeviceMgmtSvc.h:132
AthXRT::DeviceMgmtSvc::XclbinInfo::uuid
std::string uuid
Definition: DeviceMgmtSvc.h:115
XMLtoHeader.count
count
Definition: XMLtoHeader.py:85
AthXRT::DeviceMgmtSvc::XclbinInfo
Struct to hold information about an XCLBIN file, as well as the kernels it contains.
Definition: DeviceMgmtSvc.h:111
AthXRT::DeviceMgmtSvc::initialize
virtual StatusCode initialize() override
Initialise the service.
Definition: DeviceMgmtSvc.cxx:446
AthXRT::DeviceMgmtSvc::SystemInfo::device_count
std::size_t device_count
Definition: DeviceMgmtSvc.h:92
AthXRT::DeviceMgmtSvc::is_xclbin_compatible_with_device
bool is_xclbin_compatible_with_device(const DeviceMgmtSvc::XclbinInfo &xclbin_info, const cl::Device &device) const
Helper function to check if an XCLBIN file is compatible with a device.
Definition: DeviceMgmtSvc.cxx:226
ATH_MSG_ERROR
#define ATH_MSG_ERROR(x)
Definition: AthMsgStreamMacros.h:33
dqt_zlumi_pandas.err
err
Definition: dqt_zlumi_pandas.py:182
lumiFormat.i
int i
Definition: lumiFormat.py:85
AthXRT::DeviceMgmtSvc::m_xclbin_path_list
Gaudi::Property< std::vector< std::string > > m_xclbin_path_list
The list of xclbin files to use.
Definition: DeviceMgmtSvc.h:72
AthXRT::DeviceMgmtSvc::XclbinInfo::xsa_name
std::string xsa_name
Definition: DeviceMgmtSvc.h:113
beamspotman.n
n
Definition: beamspotman.py:731
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
ATH_MSG_DEBUG
#define ATH_MSG_DEBUG(x)
Definition: AthMsgStreamMacros.h:29
AthXRT::DeviceMgmtSvc::SystemInfo::device_types
std::vector< std::vector< cl::Device > > device_types
Definition: DeviceMgmtSvc.h:90
file
TFile * file
Definition: tile_monitor.h:29
AthXRT::DeviceMgmtSvc::AthClContext::devices
std::vector< cl::Device > devices
Definition: DeviceMgmtSvc.h:131
ATH_CHECK
#define ATH_CHECK
Definition: AthCheckMacros.h:40
AthXRT::DeviceMgmtSvc::get_device_name
std::string get_device_name(const cl::Device &device) const
Get the name of a cl::device.
Definition: DeviceMgmtSvc.cxx:164
histSizes.list
def list(name, path='/')
Definition: histSizes.py:38
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:228
DeviceMgmtSvc.h
AthXRT::DeviceMgmtSvc::m_ath_cl_contexts
std::vector< AthClContext > m_ath_cl_contexts
List of contexts configured for the service.
Definition: DeviceMgmtSvc.h:137
python.LumiBlobConversion.pos
pos
Definition: LumiBlobConversion.py:18
make_hlt_rep.platform
platform
Definition: make_hlt_rep.py:46
CondAlgsOpts.found
int found
Definition: CondAlgsOpts.py:101
python.CaloScaleNoiseConfig.str
str
Definition: CaloScaleNoiseConfig.py:78
ATH_MSG_WARNING
#define ATH_MSG_WARNING(x)
Definition: AthMsgStreamMacros.h:32
AthXRT::IDeviceMgmtSvc::OpenCLHandle
Struct holding OpenCL handles for a kernel.
Definition: IDeviceMgmtSvc.h:48
AthXRT::DeviceMgmtSvc::pair_devices_and_xclbins
StatusCode pair_devices_and_xclbins(const SystemInfo &si)
Pair devices and XCLBINs and create contexts.
Definition: DeviceMgmtSvc.cxx:261
get
T * get(TKey *tobj)
get a TObject* from a TKey* (why can't a TObject be a TKey?)
Definition: hcg.cxx:127
AthXRT::DeviceMgmtSvc::inspect_devices
StatusCode inspect_devices(SystemInfo &si)
Inspect the available devices and fill the SystemInfo structure.
Definition: DeviceMgmtSvc.cxx:18
AthXRT::DeviceMgmtSvc::program_devices
StatusCode program_devices()
Program the devices with the XCLBIN files and create contexts.
Definition: DeviceMgmtSvc.cxx:381
str
Definition: BTagTrackIpAccessor.cxx:11
python.dummyaccess.exists
def exists(filename)
Definition: dummyaccess.py:9
AthXRT
Definition: IDeviceMgmtSvc.h:30