Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-30 09:17:49

0001 //==========================================================================
0002 //  AIDA Detector description implementation 
0003 //--------------------------------------------------------------------------
0004 // Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN)
0005 // All rights reserved.
0006 //
0007 // For the licensing terms see $DD4hepINSTALL/LICENSE.
0008 // For the list of contributors see $DD4hepINSTALL/doc/CREDITS.
0009 //
0010 // Author     : M.Frank
0011 //
0012 //==========================================================================
0013 /* 
0014    Plugin invocation:
0015    ==================
0016    This plugin behaves like a main program.
0017    Invoke the plugin with something like this:
0018 
0019    geoPluginRun -volmgr -destroy -plugin DD4hep_ConditionExample_MT \
0020    -input file:${DD4hep_DIR}/examples/AlignDet/compact/Telescope.xml
0021 
0022    Populate the conditions store by hand for a set of IOVs.
0023    Then compute the corresponding alignment entries....
0024 
0025 */
0026 // Framework include files
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   /// Helper class to simuilate evetn queue
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   /// Helper to collect statistics
0072   class Statistics {
0073   public:
0074     /// Protection mutex for thread safe updates.
0075     mutex             total_guard;
0076     /// Total number of accesses
0077     long              total_accesses = 0;
0078     /// Total number of conditions created
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           // Now compute the tranformation matrices
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 /// Plugin function: Condition program example
0166 /**
0167  *  Factory: DD4hep_ConditionExample_stress
0168  *
0169  *  \author  M.Frank
0170  *  \version 1.0
0171  *  \date    01/12/2016
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     /// Help printout describing the basic command line interface
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   // First we load the geometry
0203   description.fromXML(input);
0204 
0205   /******************** Initialize the conditions manager *****************/
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   /******************** Now as usual: create the slice ********************/
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   /******************** Populate the conditions store *********************/
0220   // Have e.g. 10 run-slices [1,10], [11,20] .... [91,100]
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     // Create conditions with all deltas using a generic conditions creator
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     // Fill the event queue with 10 evt per run
0233     for(int j=0; j<6; ++j)   {
0234       events.push(make_pair((i*10)+j,num_run));
0235     }
0236   }
0237 
0238   // ++++++++++++++++++++++++ Now compute the conditions for each of these IOVs
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   // All done.
0255   return 1;
0256 }
0257 
0258 // first argument is the type from the xml file
0259 DECLARE_APPLY(DD4hep_ConditionExample_MT,condition_example)