ATLAS Offline Software
Loading...
Searching...
No Matches
Control/AthenaMP/python/PyComps.py
Go to the documentation of this file.
1# Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
2
3#-----Python imports---#
4import os, sys, shutil, uuid
5
6#-----Athena imports---#
7from AthenaCommon.Logging import log as msg
8
9from AthenaMP.AthenaMPConf import AthMpEvtLoopMgr
11 def __init__(self, name='AthMpEvtLoopMgr', isPileup=False, **kw):
12
13 from AthenaCommon.AppMgr import theApp
14 self.nThreads = theApp._opts.threads
15
16
17 kw['name'] = name
18 super(MpEvtLoopMgr, self).__init__(**kw)
19
20 os.putenv('XRD_ENABLEFORKHANDLERS','1')
21 os.putenv('XRD_RUNFORKHANDLER','1')
22
23 from .AthenaMPFlags import jobproperties as jp
24 self.WorkerTopDir = jp.AthenaMPFlags.WorkerTopDir()
25 self.OutputReportFile = jp.AthenaMPFlags.OutputReportFile()
26 self.CollectSubprocessLogs = jp.AthenaMPFlags.CollectSubprocessLogs()
27 self.Strategy = jp.AthenaMPFlags.Strategy()
28 self.PollingInterval = jp.AthenaMPFlags.PollingInterval()
29 self.MemSamplingInterval = jp.AthenaMPFlags.MemSamplingInterval()
30 self.EventsBeforeFork = jp.AthenaMPFlags.EventsBeforeFork()
31 self.IsPileup = isPileup
32
33 if self.Strategy=='EventService':
34 self.EventsBeforeFork = 0
35
36 from AthenaCommon.AppMgr import theApp as app
37 app.EventLoop = self.getFullJobOptName()
38
39 # Enable FileMgr logging
40 from GaudiSvc.GaudiSvcConf import FileMgr
41 from AthenaCommon.AppMgr import ServiceMgr as svcMgr
42 svcMgr+=FileMgr(LogFile="FileManagerLog")
43
44 # Save PoolFileCatalog.xml if exists in the run directory
45 if os.path.isfile('PoolFileCatalog.xml'):
46 shutil.copyfile('PoolFileCatalog.xml','PoolFileCatalog.xml.AthenaMP-saved')
47
49
50 def configureStrategy(self,strategy,pileup,events_before_fork) -> None :
51 from .AthenaMPFlags import jobproperties as jp
52 import AthenaCommon.ConcurrencyFlags # noqa: F401
53 event_range_channel = jp.AthenaMPFlags.EventRangeChannel()
54
55 chunk_size = getChunkSize()
56 if chunk_size < 1:
57 msg.warning('Nonpositive ChunkSize (%i) caught, setting it to 1', chunk_size)
58 chunk_size = 1
59
60 debug_worker = jp.ConcurrencyFlags.DebugWorkers()
61 use_shared_reader = jp.AthenaMPFlags.UseSharedReader()
62 use_shared_writer = jp.AthenaMPFlags.UseSharedWriter()
63 use_parallel_compression = jp.AthenaMPFlags.UseParallelCompression()
64 unique_id = f"{str(os.getpid())}-{uuid.uuid4().hex}"
65
66 # For e.g. event generation, if we use SharedQueue the job does not complete correctly
67 if strategy == 'SharedQueue':
68 from AthenaCommon.AthenaCommonFlags import jobproperties as ajp
69 if (not ajp.AthenaCommonFlags.FilesInput.statusOn) or ajp.AthenaCommonFlags.FilesInput == []:
70 msg.info('MP strategy "SharedQueue" will not work without input files when maxEvents=-1. Switching to "RoundRobin" just in case')
71 strategy = 'RoundRobin'
72
73 if strategy=='SharedQueue' or strategy=='RoundRobin':
74 if use_shared_reader:
75 from AthenaCommon.AppMgr import ServiceMgr as svcMgr
76 # Currently SharedReader uses single PersSvc for event & cond, so we can't age files.
77 svcMgr.PoolSvc.MaxFilesOpen = 0
78 if use_shared_writer:
79 from AthenaCommon.AppMgr import ServiceMgr as svcMgr
80 if 'AthenaPoolCnvSvc.WriteAthenaPool' in sys.modules:
81 from AthenaIPCTools.AthenaIPCToolsConf import AthenaSharedMemoryTool
82 svcMgr.AthenaPoolCnvSvc.OutputStreamingTool = AthenaSharedMemoryTool("OutputStreamingTool", SharedMemoryName=f"OutputStream{unique_id}")
83 svcMgr.AthenaPoolCnvSvc.ParallelCompression=use_parallel_compression
84
85 if strategy=='SharedQueue':
86 from AthenaMPTools.AthenaMPToolsConf import SharedEvtQueueProvider
87 self.Tools += [ SharedEvtQueueProvider(UseSharedReader=use_shared_reader,
88 IsPileup=pileup,
89 EventsBeforeFork=events_before_fork,
90 ChunkSize=chunk_size) ]
91
92 # In pure MP, self.nThreads may be set to None - we want the pure MP setup in that case
93 if self.nThreads is not None and self.nThreads >= 1:
94 if(pileup):
95 raise Exception('Running pileup digitization in mixed MP+MT currently not supported')
96 from AthenaMPTools.AthenaMPToolsConf import SharedHiveEvtQueueConsumer
97 self.Tools += [ SharedHiveEvtQueueConsumer(UseSharedWriter=use_shared_writer,
98 EventsBeforeFork=events_before_fork,
99 Debug=debug_worker) ]
100 else:
101 from AthenaMPTools.AthenaMPToolsConf import SharedEvtQueueConsumer
102 self.Tools += [ SharedEvtQueueConsumer(UseSharedReader=use_shared_reader,
103 UseSharedWriter=use_shared_writer,
104 IsPileup=pileup,
105 IsRoundRobin=(strategy=='RoundRobin'),
106 EventsBeforeFork=events_before_fork,
107 ReadEventOrders=jp.AthenaMPFlags.ReadEventOrders(),
108 EventOrdersFile=jp.AthenaMPFlags.EventOrdersFile(),
109 Debug=debug_worker) ]
110 if use_shared_writer:
111 from AthenaMPTools.AthenaMPToolsConf import SharedWriterTool
112 self.Tools += [ SharedWriterTool(MotherProcess=(events_before_fork>0),
113 IsPileup=pileup,
114 Debug=debug_worker) ]
115 elif strategy=='EventService':
116 channelScatterer2Processor = "AthenaMP_Scatterer2Processor"
117 channelProcessor2EvtSel = "AthenaMP_Processor2EvtSel"
118
119 from AthenaMPTools.AthenaMPToolsConf import EvtRangeScatterer
120 self.Tools += [ EvtRangeScatterer(ProcessorChannel = channelScatterer2Processor,
121 EventRangeChannel = event_range_channel,
122 DoCaching=jp.AthenaMPFlags.EvtRangeScattererCaching()) ]
123
124 from AthenaMPTools.AthenaMPToolsConf import EvtRangeProcessor
125 self.Tools += [ EvtRangeProcessor(IsPileup=pileup,
126 Channel2Scatterer = channelScatterer2Processor,
127 Channel2EvtSel = channelProcessor2EvtSel,
128 Debug=debug_worker) ]
129 else:
130 msg.warning("Unknown strategy. No MP tools will be configured")
131
132def getChunkSize() -> int :
133 from .AthenaMPFlags import jobproperties as jp
134 from PyUtils.MetaReaderPeeker import metadata
135 chunk_size = 1
136 # In jobs without input (e.g. event generation), metadata is an empty dictionary
137 if (jp.AthenaMPFlags.ChunkSize() > 0):
138 chunk_size = jp.AthenaMPFlags.ChunkSize()
139 msg.info('Chunk size set to %i', chunk_size)
140 elif 'file_size' in metadata and metadata['file_size'] is not None:
141 #Don't use auto flush for shared reader
142 if (jp.AthenaMPFlags.UseSharedReader()):
143 msg.info('Shared Reader in use, chunk_size set to default (%i)', chunk_size)
144 #Use auto flush only if file is compressed with LZMA, else use default chunk_size
145 elif (jp.AthenaMPFlags.ChunkSize() == -1):
146 if (metadata['file_comp_alg'] == 2):
147 chunk_size = metadata['auto_flush']
148 msg.info('Chunk size set to auto flush (%i)', chunk_size)
149 else:
150 msg.info('LZMA algorithm not in use, chunk_size set to default (%i)', chunk_size)
151 #Use auto flush only if file is compressed with LZMA or ZLIB, else use default chunk_size
152 elif (jp.AthenaMPFlags.ChunkSize() == -2):
153 if (metadata['file_comp_alg'] == 1 or metadata['file_comp_alg'] == 2):
154 chunk_size = metadata['auto_flush']
155 msg.info('Chunk size set to auto flush (%i)', chunk_size)
156 else:
157 msg.info('LZMA nor ZLIB in use, chunk_size set to default (%i)', chunk_size)
158 #Use auto flush only if file is compressed with LZMA, ZLIB or LZ4, else use default chunk_size
159 elif (jp.AthenaMPFlags.ChunkSize() == -3):
160 if (metadata['file_comp_alg'] == 1 or metadata['file_comp_alg'] == 2 or metadata['file_comp_alg'] == 4):
161 chunk_size = metadata['auto_flush']
162 msg.info('Chunk size set to auto flush (%i)', chunk_size)
163 else:
164 msg.info('LZMA, ZLIB nor LZ4 in use, chunk_size set to (%i)', chunk_size)
165 #Use auto flush value for chunk_size, regarldess of compression algorithm
166 elif (jp.AthenaMPFlags.ChunkSize() <= -4):
167 chunk_size = metadata['auto_flush']
168 msg.info('Chunk size set to auto flush (%i)', chunk_size)
169 else:
170 msg.warning('Invalid ChunkSize, Chunk Size set to default (%i)', chunk_size)
171
172 return chunk_size
if(pathvar)
This class provides the IPCTool for SharedMemory objects.
None configureStrategy(self, strategy, pileup, events_before_fork)
__init__(self, name='AthMpEvtLoopMgr', isPileup=False, **kw)