Commit 4c5082b89e72f9baaf2258218a0e3912861afd26

Authored by Jean-Baptiste CAYROU
1 parent f4de261c

Parallelize the simulation loop

pyext/ctobssim.i
... ... @@ -52,8 +52,8 @@ public:
52 52 GObservations& obs(void);
53 53 void get_parameters(void);
54 54 void set_list(GCTAObservation* obs);
55   - void simulate_source(GCTAObservation* obs, const GModels& models);
56   - void simulate_background(GCTAObservation* obs, const GModels& models);
  55 + void simulate_source(GCTAObservation* obs, const GModels& models, GRan& ran, GLog* wrklog=NULL);
  56 + void simulate_background(GCTAObservation* obs, const GModels& models, GRan& ran, GLog* wrklog=NULL);
57 57 };
58 58  
59 59  
... ...
src/ctobssim/ctobssim.cpp
... ... @@ -264,38 +264,44 @@ void ctobssim::run(void)
264 264 // Initialise counters
265 265 int n_observations = 0;
266 266  
267   - // Loop over all observation in the container
268   - for (int i = 0; i < m_obs.size(); ++i) {
269   -
270   - // Get CTA observation
271   - GCTAObservation* obs = dynamic_cast<GCTAObservation*>(&m_obs[i]);
272   -
273   - // Continue only if observation is a CTA observation
274   - if (obs != NULL) {
275   -
276   - // Write header for observation
277   - if (logTerse()) {
278   - if (obs->name().length() > 1) {
279   - log.header3("Observation "+obs->name());
280   - }
281   - else {
282   - log.header3("Observation");
283   - }
284   - }
285   -
286   - // Increment counter
287   - n_observations++;
288   -
289   - // Simulate source events
290   - simulate_source(obs, m_obs.models());
291   -
292   - // Simulate source events
293   - simulate_background(obs, m_obs.models());
294   -
295   - } // endif: CTA observation found
296   -
297   - } // endfor: looped over observations
  267 + #pragma omp parallel
  268 + {
  269 + //each thread has his own variable;
  270 + GLog wrklog(log);
  271 +
  272 + #pragma omp for
  273 + // Loop over all observation in the container
  274 + for (int i = 0; i < m_obs.size(); ++i) {
  275 +
  276 + // Get CTA observation
  277 + GCTAObservation* obs = dynamic_cast<GCTAObservation*>(&m_obs[i]);
  278 +
  279 + // Continue only if observation is a CTA observation
  280 + if (obs != NULL) {
  281 + // Write header for observation
  282 + if (logTerse()) {
  283 + if (obs->name().length() > 1) {
  284 + wrklog.header3("Observation "+obs->name());
  285 + }
  286 + else {
  287 + wrklog.header3("Observation");
  288 + }
  289 + }
  290 + // Increment counter
  291 + n_observations++;
  292 +
  293 + // Simulate source events
  294 + simulate_source(obs, m_obs.models(),m_rans[i],&wrklog);
  295 +
  296 + // Simulate source events
  297 + simulate_background(obs, m_obs.models(),m_rans[i],&wrklog);
  298 +
  299 + } // endif: CTA observation found
  300 +
  301 + } // endfor: looped over observations
298 302  
  303 + } // end pragma omp parallel
  304 +
299 305 // If more than a single observation has been handled then make sure that
300 306 // an XML file will be used for storage
301 307 if (n_observations > 1) {
... ... @@ -419,7 +425,36 @@ void ctobssim::get_parameters(void)
419 425 }
420 426  
421 427 // Initialise random number generator
422   - m_ran.seed(m_seed);
  428 + //m_ran.seed(m_seed);
  429 +
  430 + GRan master(m_seed);
  431 + std::vector<unsigned long long int> seeds;
  432 +
  433 + bool repeat = false;
  434 +
  435 + // Loop over all observation in the container
  436 + for (int i = 0; i < m_obs.size(); ++i) {
  437 + unsigned long long int new_seed;
  438 +
  439 + do {
  440 + // Each seed will be unique
  441 + new_seed = (unsigned long long int)(master.int64() * 1.0e2);
  442 + repeat = false;
  443 + for (int j = 0; j < seeds.size(); ++j) {
  444 + if (new_seed == seeds[j]) {
  445 + repeat = true;
  446 + break;
  447 + }
  448 + }
  449 + } while(repeat);
  450 +
  451 + //Add the seed to the vector
  452 + seeds.push_back(new_seed);
  453 +
  454 + //Use the seed to create a GRan for the observation number i
  455 + m_rans.push_back(GRan(new_seed));
  456 + }
  457 +
423 458  
424 459 // Return
425 460 return;
... ... @@ -524,11 +559,15 @@ void ctobssim::set_list(GCTAObservation* obs)
524 559 * they can be scatter within the ROI and energy interval by the
525 560 * PSF and energy dispersion.
526 561 ***************************************************************************/
527   -void ctobssim::simulate_source(GCTAObservation* obs, const GModels& models)
  562 +void ctobssim::simulate_source(GCTAObservation* obs, const GModels& models, GRan& ran, GLog* wrklog)
528 563 {
529 564 // Continue only if observation pointer is valid
530 565 if (obs != NULL) {
531   -
  566 +
  567 + if(wrklog==NULL){
  568 + wrklog=&log;
  569 + }
  570 +
532 571 // Get pointer on CTA response. Throw an exception if the response
533 572 // is not defined.
534 573 GCTAResponse* rsp = obs->response();
... ... @@ -551,12 +590,12 @@ void ctobssim::simulate_source(GCTAObservation* obs, const GModels&amp; models)
551 590  
552 591 // Dump simulation cone information
553 592 if (logNormal()) {
554   - log << parformat("Simulation area");
555   - log << str(m_area) << " cm2" << std::endl;
556   - log << parformat("Simulation cone");
557   - log << "RA=" << dir.ra_deg() << " deg";
558   - log << ", Dec=" << dir.dec_deg() << " deg";
559   - log << ", r=" << rad << " deg" << std::endl;
  593 + *wrklog << parformat("Simulation area");
  594 + *wrklog << str(m_area) << " cm2" << std::endl;
  595 + *wrklog << parformat("Simulation cone");
  596 + *wrklog << "RA=" << dir.ra_deg() << " deg";
  597 + *wrklog << ", Dec=" << dir.dec_deg() << " deg";
  598 + *wrklog << ", r=" << rad << " deg" << std::endl;
560 599 }
561 600  
562 601 // Initialise indentation for logging
... ... @@ -573,10 +612,10 @@ void ctobssim::simulate_source(GCTAObservation* obs, const GModels&amp; models)
573 612 if (logNormal()) {
574 613 if (events->gti().size() > 1) {
575 614 indent++;
576   - log.indent(indent);
  615 + wrklog->indent(indent);
577 616 }
578   - log << parformat("Time interval");
579   - log << tmin << " - " << tmax << std::endl;
  617 + *wrklog << parformat("Time interval");
  618 + *wrklog << tmin << " - " << tmax << std::endl;
580 619 }
581 620  
582 621 // Loop over all energy boundaries
... ... @@ -590,10 +629,10 @@ void ctobssim::simulate_source(GCTAObservation* obs, const GModels&amp; models)
590 629 if (logNormal()) {
591 630 if (events->ebounds().size() > 1) {
592 631 indent++;
593   - log.indent(indent);
  632 + wrklog->indent(indent);
594 633 }
595   - log << parformat("Energy range");
596   - log << emin << " - " << emax << std::endl;
  634 + *wrklog << parformat("Energy range");
  635 + *wrklog << emin << " - " << emax << std::endl;
597 636 }
598 637  
599 638 // Loop over all sky models
... ... @@ -627,16 +666,17 @@ void ctobssim::simulate_source(GCTAObservation* obs, const GModels&amp; models)
627 666 if (logExplicit()) {
628 667 if (tmax - tmin > m_time_max) {
629 668 indent++;
630   - log.indent(indent);
  669 + wrklog->indent(indent);
631 670 }
632   - log << parformat("Time slice");
633   - log << tstart << " - " << tstop << std::endl;
  671 + *wrklog << parformat("Time slice");
  672 + *wrklog << tstart << " - " << tstop << std::endl;
  673 +
634 674 }
635 675  
636 676 // Get photons
637 677 GPhotons photons = model->mc(m_area, dir, rad,
638 678 emin, emax,
639   - tstart, tstop, m_ran);
  679 + tstart, tstop, ran);
640 680  
641 681 // Simulate events from photons
642 682 for (int i = 0; i < photons.size(); ++i) {
... ... @@ -649,7 +689,7 @@ void ctobssim::simulate_source(GCTAObservation* obs, const GModels&amp; models)
649 689 GCTAEventAtom* event = rsp->mc(m_area,
650 690 photons[i],
651 691 *obs,
652   - m_ran);
  692 + ran);
653 693 if (event != NULL) {
654 694 events->append(*event);
655 695 delete event;
... ... @@ -665,7 +705,7 @@ void ctobssim::simulate_source(GCTAObservation* obs, const GModels&amp; models)
665 705 if (logExplicit()) {
666 706 if (tmax - tmin > m_time_max) {
667 707 indent--;
668   - log.indent(indent);
  708 + wrklog->indent(indent);
669 709 }
670 710 }
671 711  
... ... @@ -673,18 +713,19 @@ void ctobssim::simulate_source(GCTAObservation* obs, const GModels&amp; models)
673 713  
674 714 // Dump simulation results
675 715 if (logNormal()) {
676   - log << parformat("MC source photons");
677   - log << str(nphotons);
  716 + *wrklog << parformat("MC source photons");
  717 + *wrklog << str(nphotons);
678 718 if (model->name().length() > 0) {
679   - log << " [" << model->name() << "]";
  719 + *wrklog << " [" << model->name() << "]";
680 720 }
681   - log << std::endl;
682   - log << parformat("MC source events");
683   - log << str(events->size());
  721 + *wrklog << std::endl;
  722 + *wrklog << parformat("MC source events");
  723 + *wrklog << str(events->size());
684 724 if (model->name().length() > 0) {
685   - log << " [" << model->name() << "]";
  725 + *wrklog << " [" << model->name() << "]";
686 726 }
687   - log << std::endl;
  727 + *wrklog << std::endl;
  728 +
688 729 }
689 730  
690 731 } // endif: model was a sky model
... ... @@ -693,17 +734,18 @@ void ctobssim::simulate_source(GCTAObservation* obs, const GModels&amp; models)
693 734  
694 735 // Dump simulation results
695 736 if (logNormal()) {
696   - log << parformat("MC source events");
697   - log << str(events->size());
698   - log << " (all source models)";
699   - log << std::endl;
  737 + *wrklog << parformat("MC source events");
  738 + *wrklog << str(events->size());
  739 + *wrklog << " (all source models)";
  740 + *wrklog << std::endl;
700 741 }
701 742  
702 743 // Reset indentation
703 744 if (logNormal()) {
704 745 if (events->ebounds().size() > 1) {
705 746 indent--;
706   - log.indent(indent);
  747 + wrklog->indent(indent);
  748 +
707 749 }
708 750 }
709 751  
... ... @@ -713,14 +755,15 @@ void ctobssim::simulate_source(GCTAObservation* obs, const GModels&amp; models)
713 755 if (logNormal()) {
714 756 if (events->gti().size() > 1) {
715 757 indent--;
716   - log.indent(indent);
  758 + wrklog->indent(indent);
  759 +
717 760 }
718 761 }
719 762  
720 763 } // endfor: looped over all time intervals
721 764  
722 765 // Reset indentation
723   - log.indent(0);
  766 + wrklog->indent(0);
724 767  
725 768 } // endif: observation pointer was valid
726 769  
... ... @@ -740,11 +783,15 @@ void ctobssim::simulate_source(GCTAObservation* obs, const GModels&amp; models)
740 783 *
741 784 * This method does nothing if the observation pointer is NULL.
742 785 ***************************************************************************/
743   -void ctobssim::simulate_background(GCTAObservation* obs, const GModels& models)
  786 +void ctobssim::simulate_background(GCTAObservation* obs, const GModels& models, GRan& ran, GLog* wrklog)
744 787 {
745 788 // Continue only if observation pointer is valid
746 789 if (obs != NULL) {
747 790  
  791 + if(wrklog==NULL){
  792 + wrklog=&log;
  793 + }
  794 +
748 795 // Make sure that the observation holds a CTA event list. If this
749 796 // is not the case then allocate and attach a CTA event list now.
750 797 if (dynamic_cast<const GCTAEventList*>(obs->events()) == NULL) {
... ... @@ -766,7 +813,7 @@ void ctobssim::simulate_background(GCTAObservation* obs, const GModels&amp; models)
766 813  
767 814 // Get simulated event list. Note that this method includes
768 815 // the deadtime correction.
769   - GCTAEventList* list = model->mc(*obs, m_ran);
  816 + GCTAEventList* list = model->mc(*obs, ran);
770 817  
771 818 // Reserves space for events
772 819 events->reserve(list->size()+events->size());
... ... @@ -784,8 +831,8 @@ void ctobssim::simulate_background(GCTAObservation* obs, const GModels&amp; models)
784 831  
785 832 // Dump simulation results
786 833 if (logNormal()) {
787   - log << parformat("MC background events");
788   - log << str(list->size()) << std::endl;
  834 + *wrklog << parformat("MC background events");
  835 + *wrklog << str(list->size()) << std::endl;
789 836 }
790 837  
791 838 // Free event list
... ... @@ -875,7 +922,7 @@ void ctobssim::copy_members(const ctobssim&amp; app)
875 922 // Copy protected members
876 923 m_area = app.m_area;
877 924 m_time_max = app.m_time_max;
878   - m_ran = app.m_ran;
  925 + m_rans = app.m_rans;
879 926 m_obs = app.m_obs;
880 927 m_use_xml = app.m_use_xml;
881 928 m_read_ahead = app.m_read_ahead;
... ...
src/ctobssim/ctobssim.hpp
... ... @@ -67,8 +67,8 @@ public:
67 67 GObservations& obs(void) { return m_obs; }
68 68 void get_parameters(void);
69 69 void set_list(GCTAObservation* obs);
70   - void simulate_source(GCTAObservation* obs, const GModels& models);
71   - void simulate_background(GCTAObservation* obs, const GModels& models);
  70 + void simulate_source(GCTAObservation* obs, const GModels& models,GRan& ran, GLog* wrklog=NULL);
  71 + void simulate_background(GCTAObservation* obs, const GModels& models,GRan& ran, GLog* wrklog=NULL);
72 72  
73 73 protected:
74 74 // Protected methods
... ... @@ -97,7 +97,8 @@ protected:
97 97 // Protected members
98 98 double m_area; //!< Surface area for simulation (cm2)
99 99 GTime m_time_max; //!< Maximum length of time slice (sec)
100   - GRan m_ran; //!< Random number generator
  100 + //GRan m_ran; //!< Random number generator
  101 + std::vector<GRan> m_rans; //!< Random number generators
101 102 GObservations m_obs; //!< Observation container
102 103 bool m_use_xml; //!< Use XML file instead of FITS file
103 104 bool m_read_ahead; //!< Read ahead parameters
... ...