File indexing completed on 2025-01-30 09:17:49
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027 #include "ConditionExampleObjects.h"
0028 #include "DDCond/ConditionsManagerObject.h"
0029 #include "DD4hep/Factories.h"
0030 #include "TStatistic.h"
0031 #include "TTimeStamp.h"
0032 #include "TRandom3.h"
0033
0034 #include <mutex>
0035 #include <thread>
0036 #include <unistd.h>
0037
0038 using namespace std;
0039 using namespace dd4hep;
0040 using namespace dd4hep::ConditionExamples;
0041
0042 namespace {
0043 mutex printout_lock;
0044
0045
0046 class EventQueue {
0047 vector<std::pair<long,long> > events;
0048 mutex guard;
0049 public:
0050 EventQueue() = default;
0051 ~EventQueue() = default;
0052 void push(const std::pair<long,long>& e) {
0053 lock_guard<mutex> lock(guard);
0054 events.push_back(e);
0055 }
0056 long get() {
0057 if ( !events.empty() ) {
0058 lock_guard<mutex> lock(guard);
0059 if ( !events.empty() ) {
0060 pair<long,long>& last = events.back();
0061 if ( --last.second > 0 )
0062 return last.first;
0063 long iov = last.first;
0064 events.pop_back();
0065 return iov;
0066 }
0067 }
0068 return -1;
0069 }
0070 };
0071
0072 class Statistics {
0073 public:
0074
0075 mutex total_guard;
0076
0077 long total_accesses = 0;
0078
0079 long total_created = 0;
0080 ConditionsManager::Result totals;
0081 TStatistic create, prepare, access;
0082 Statistics() : create("Creation"), prepare("Prepare"), access("Access") { }
0083 void print() const {
0084 printout(INFO,"Statistics","+ %-12s: %11.5g +- %11.4g RMS = %11.5g N = %lld",
0085 create.GetName(), create.GetMean(), create.GetMeanErr(),
0086 create.GetRMS(), create.GetN());
0087 printout(INFO,"Statistics","+ %-12s: %11.5g +- %11.4g RMS = %11.5g N = %lld",
0088 prepare.GetName(), prepare.GetMean(), prepare.GetMeanErr(),
0089 prepare.GetRMS(), prepare.GetN());
0090 printout(INFO,"Statistics","+ %-12s: %11.5g +- %11.4g RMS = %11.5g N = %lld",
0091 access.GetName(), access.GetMean(), access.GetMeanErr(),
0092 access.GetRMS(), access.GetN());
0093 printout(INFO,"Statistics","+ Accessed a total of %ld conditions (S:%6ld,L:%6ld,C:%6ld,M:%ld) during the test. Created:%ld",
0094 total_accesses, totals.selected, totals.loaded, totals.computed, totals.missing, total_created);
0095 printout(INFO,"Statistics","+=========================================================================");
0096 }
0097 };
0098
0099 class Executor {
0100 public:
0101 ConditionsManager manager;
0102 EventQueue& events;
0103 ConditionsSlice* slice;
0104 const IOVType* iovTyp;
0105 Statistics& stats;
0106 int identifier;
0107
0108 Executor(ConditionsManager m, const IOVType* typ, int id, EventQueue& q, Statistics& s)
0109 : manager(m), events(q), slice(0), iovTyp(typ), stats(s), identifier(id)
0110 {
0111 }
0112 virtual ~Executor() {
0113 delete slice;
0114 }
0115 int accessConditions(const IOV& iov) {
0116 TTimeStamp start;
0117 int count = Scanner().scan(ConditionsDataAccess(iov,*slice),manager->detectorDescription().world());
0118 TTimeStamp stop;
0119 stats.access.Fill(stop.AsDouble()-start.AsDouble());
0120 lock_guard<mutex> lock(stats.total_guard);
0121 stats.total_accesses += count;
0122 return count;
0123 }
0124 void run() {
0125 int num_reuse = 0;
0126 int num_access = 0;
0127 ConditionsManager::Result res;
0128 for(long iov_val=events.get(), last_iov=-1; iov_val>0; iov_val=events.get()) {
0129 IOV iov(iovTyp, iov_val);
0130 if ( iov_val != last_iov ) {
0131 TTimeStamp start;
0132 IOV pool_iov(slice->pool.get() ? slice->pool->validity() : iov);
0133 res = manager.prepare(iov,*slice);
0134 TTimeStamp stop;
0135 stats.prepare.Fill(stop.AsDouble()-start.AsDouble());
0136 last_iov = iov_val;
0137
0138 {
0139 lock_guard<mutex> lock(printout_lock);
0140 printout(INFO,"Re-use","Thread:%3d Conditions reused: %d times. "
0141 "Number of accesses:%d IOV:%s",
0142 identifier, num_reuse, num_access, pool_iov.str().c_str());
0143 printout(INFO,"Prepare","Thread:%3d Total %ld conditions (S:%6ld,L:%6ld,C:%6ld,M:%ld) of type %s [%8.3f sec]",
0144 identifier, res.total(), res.selected, res.loaded, res.computed, res.missing,
0145 iov.str().c_str(), stop.AsDouble()-start.AsDouble());
0146 }
0147 num_access = accessConditions(iov);
0148 num_reuse = 0;
0149 stats.total_guard.lock();
0150 stats.totals += res;
0151 stats.total_guard.unlock();
0152 continue;
0153 }
0154 ++num_reuse;
0155 ::usleep(10000);
0156 num_access += accessConditions(iov);
0157 stats.total_guard.lock();
0158 stats.totals += res;
0159 stats.total_guard.unlock();
0160 }
0161 }
0162 };
0163 }
0164
0165
0166
0167
0168
0169
0170
0171
0172
0173 static int condition_example (Detector& description, int argc, char** argv) {
0174 string input;
0175 int num_iov = 10, num_threads = 1, num_run = 30;
0176 bool arg_error = false;
0177 for(int i=0; i<argc && argv[i]; ++i) {
0178 if ( 0 == ::strncmp("-input",argv[i],4) )
0179 input = argv[++i];
0180 else if ( 0 == ::strncmp("-iovs",argv[i],4) )
0181 num_iov = ::atol(argv[++i]);
0182 else if ( 0 == ::strncmp("-runs",argv[i],4) )
0183 num_run = ::atol(argv[++i]);
0184 else if ( 0 == ::strncmp("-threads",argv[i],4) )
0185 num_threads = ::atol(argv[++i]);
0186 else
0187 arg_error = true;
0188 }
0189 if ( arg_error || input.empty() ) {
0190
0191 cout <<
0192 "Usage: -plugin <name> -arg [-arg] \n"
0193 " name: factory name DD4hep_ConditionExample_MT \n"
0194 " -input <string> Geometry file \n"
0195 " -iovs <number> Number of parallel IOV slots for processing. \n"
0196 " -runs <number> Number of collision loads to be performed. \n"
0197 " -threads <number> Number of execution threads. \n"
0198 "\tArguments given: " << arguments(argc,argv) << endl << flush;
0199 ::exit(EINVAL);
0200 }
0201
0202
0203 description.fromXML(input);
0204
0205
0206 ConditionsManager manager = installManager(description);
0207 const IOVType* iov_typ = manager.registerIOVType(0,"run").second;
0208 if ( 0 == iov_typ )
0209 except("ConditionsPrepare","++ Unknown IOV type supplied.");
0210
0211
0212 shared_ptr<ConditionsContent> content(new ConditionsContent());
0213 shared_ptr<ConditionsSlice> slice(new ConditionsSlice(manager,content));
0214 Scanner(ConditionsKeys(*content,INFO),description.world());
0215 Scanner(ConditionsDependencyCreator(*content,DEBUG),description.world());
0216
0217 Statistics stats;
0218 EventQueue events;
0219
0220
0221 for(int i=0; i<num_iov; ++i) {
0222 TTimeStamp start;
0223 IOV iov(iov_typ, IOV::Key(1+i*10,(i+1)*10));
0224 ConditionsPool* pool = manager.registerIOV(*iov.iovType, iov.key());
0225
0226 int count = Scanner().scan(ConditionsCreator(*slice, *pool, DEBUG),description.world());
0227 TTimeStamp stop;
0228 stats.create.Fill(stop.AsDouble()-start.AsDouble());
0229 printout(INFO,"Example", "Setup %ld conditions for IOV:%s [%8.3f sec]",
0230 count, iov.str().c_str(),stop.AsDouble()-start.AsDouble());
0231 stats.total_created += count;
0232
0233 for(int j=0; j<6; ++j) {
0234 events.push(make_pair((i*10)+j,num_run));
0235 }
0236 }
0237
0238
0239 vector<thread*> threads;
0240 for(int i=0; i<num_threads; ++i) {
0241 Executor* exec = new Executor(manager, iov_typ, i, events, stats);
0242 exec->slice = new ConditionsSlice(*slice);
0243 thread* t = new thread( [exec]{ exec->run(); delete exec; });
0244 threads.push_back(t);
0245 }
0246 for(thread* t : threads) {
0247 t->join();
0248 delete t;
0249 }
0250 printout(INFO,"Statistics",
0251 "+======= Summary: # of IOV: %3d # of Threads: %3d ========================",
0252 num_iov, num_threads);
0253 stats.print();
0254
0255 return 1;
0256 }
0257
0258
0259 DECLARE_APPLY(DD4hep_ConditionExample_MT,condition_example)