Commit 4c5082b89e72f9baaf2258218a0e3912861afd26

Authored by Jean-Baptiste CAYROU
1 parent f4de261c

Parallelize the simulation loop

pyext/ctobssim.i
@@ -52,8 +52,8 @@ public: @@ -52,8 +52,8 @@ public:
52 GObservations& obs(void); 52 GObservations& obs(void);
53 void get_parameters(void); 53 void get_parameters(void);
54 void set_list(GCTAObservation* obs); 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,38 +264,44 @@ void ctobssim::run(void)
264 // Initialise counters 264 // Initialise counters
265 int n_observations = 0; 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 // If more than a single observation has been handled then make sure that 305 // If more than a single observation has been handled then make sure that
300 // an XML file will be used for storage 306 // an XML file will be used for storage
301 if (n_observations > 1) { 307 if (n_observations > 1) {
@@ -419,7 +425,36 @@ void ctobssim::get_parameters(void) @@ -419,7 +425,36 @@ void ctobssim::get_parameters(void)
419 } 425 }
420 426
421 // Initialise random number generator 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 // Return 459 // Return
425 return; 460 return;
@@ -524,11 +559,15 @@ void ctobssim::set_list(GCTAObservation* obs) @@ -524,11 +559,15 @@ void ctobssim::set_list(GCTAObservation* obs)
524 * they can be scatter within the ROI and energy interval by the 559 * they can be scatter within the ROI and energy interval by the
525 * PSF and energy dispersion. 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 // Continue only if observation pointer is valid 564 // Continue only if observation pointer is valid
530 if (obs != NULL) { 565 if (obs != NULL) {
531 - 566 +
  567 + if(wrklog==NULL){
  568 + wrklog=&log;
  569 + }
  570 +
532 // Get pointer on CTA response. Throw an exception if the response 571 // Get pointer on CTA response. Throw an exception if the response
533 // is not defined. 572 // is not defined.
534 GCTAResponse* rsp = obs->response(); 573 GCTAResponse* rsp = obs->response();
@@ -551,12 +590,12 @@ void ctobssim::simulate_source(GCTAObservation* obs, const GModels&amp; models) @@ -551,12 +590,12 @@ void ctobssim::simulate_source(GCTAObservation* obs, const GModels&amp; models)
551 590
552 // Dump simulation cone information 591 // Dump simulation cone information
553 if (logNormal()) { 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 // Initialise indentation for logging 601 // Initialise indentation for logging
@@ -573,10 +612,10 @@ void ctobssim::simulate_source(GCTAObservation* obs, const GModels&amp; models) @@ -573,10 +612,10 @@ void ctobssim::simulate_source(GCTAObservation* obs, const GModels&amp; models)
573 if (logNormal()) { 612 if (logNormal()) {
574 if (events->gti().size() > 1) { 613 if (events->gti().size() > 1) {
575 indent++; 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 // Loop over all energy boundaries 621 // Loop over all energy boundaries
@@ -590,10 +629,10 @@ void ctobssim::simulate_source(GCTAObservation* obs, const GModels&amp; models) @@ -590,10 +629,10 @@ void ctobssim::simulate_source(GCTAObservation* obs, const GModels&amp; models)
590 if (logNormal()) { 629 if (logNormal()) {
591 if (events->ebounds().size() > 1) { 630 if (events->ebounds().size() > 1) {
592 indent++; 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 // Loop over all sky models 638 // Loop over all sky models
@@ -627,16 +666,17 @@ void ctobssim::simulate_source(GCTAObservation* obs, const GModels&amp; models) @@ -627,16 +666,17 @@ void ctobssim::simulate_source(GCTAObservation* obs, const GModels&amp; models)
627 if (logExplicit()) { 666 if (logExplicit()) {
628 if (tmax - tmin > m_time_max) { 667 if (tmax - tmin > m_time_max) {
629 indent++; 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 // Get photons 676 // Get photons
637 GPhotons photons = model->mc(m_area, dir, rad, 677 GPhotons photons = model->mc(m_area, dir, rad,
638 emin, emax, 678 emin, emax,
639 - tstart, tstop, m_ran); 679 + tstart, tstop, ran);
640 680
641 // Simulate events from photons 681 // Simulate events from photons
642 for (int i = 0; i < photons.size(); ++i) { 682 for (int i = 0; i < photons.size(); ++i) {
@@ -649,7 +689,7 @@ void ctobssim::simulate_source(GCTAObservation* obs, const GModels&amp; models) @@ -649,7 +689,7 @@ void ctobssim::simulate_source(GCTAObservation* obs, const GModels&amp; models)
649 GCTAEventAtom* event = rsp->mc(m_area, 689 GCTAEventAtom* event = rsp->mc(m_area,
650 photons[i], 690 photons[i],
651 *obs, 691 *obs,
652 - m_ran); 692 + ran);
653 if (event != NULL) { 693 if (event != NULL) {
654 events->append(*event); 694 events->append(*event);
655 delete event; 695 delete event;
@@ -665,7 +705,7 @@ void ctobssim::simulate_source(GCTAObservation* obs, const GModels&amp; models) @@ -665,7 +705,7 @@ void ctobssim::simulate_source(GCTAObservation* obs, const GModels&amp; models)
665 if (logExplicit()) { 705 if (logExplicit()) {
666 if (tmax - tmin > m_time_max) { 706 if (tmax - tmin > m_time_max) {
667 indent--; 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,18 +713,19 @@ void ctobssim::simulate_source(GCTAObservation* obs, const GModels&amp; models)
673 713
674 // Dump simulation results 714 // Dump simulation results
675 if (logNormal()) { 715 if (logNormal()) {
676 - log << parformat("MC source photons");  
677 - log << str(nphotons); 716 + *wrklog << parformat("MC source photons");
  717 + *wrklog << str(nphotons);
678 if (model->name().length() > 0) { 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 if (model->name().length() > 0) { 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 } // endif: model was a sky model 731 } // endif: model was a sky model
@@ -693,17 +734,18 @@ void ctobssim::simulate_source(GCTAObservation* obs, const GModels&amp; models) @@ -693,17 +734,18 @@ void ctobssim::simulate_source(GCTAObservation* obs, const GModels&amp; models)
693 734
694 // Dump simulation results 735 // Dump simulation results
695 if (logNormal()) { 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 // Reset indentation 743 // Reset indentation
703 if (logNormal()) { 744 if (logNormal()) {
704 if (events->ebounds().size() > 1) { 745 if (events->ebounds().size() > 1) {
705 indent--; 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,14 +755,15 @@ void ctobssim::simulate_source(GCTAObservation* obs, const GModels&amp; models)
713 if (logNormal()) { 755 if (logNormal()) {
714 if (events->gti().size() > 1) { 756 if (events->gti().size() > 1) {
715 indent--; 757 indent--;
716 - log.indent(indent); 758 + wrklog->indent(indent);
  759 +
717 } 760 }
718 } 761 }
719 762
720 } // endfor: looped over all time intervals 763 } // endfor: looped over all time intervals
721 764
722 // Reset indentation 765 // Reset indentation
723 - log.indent(0); 766 + wrklog->indent(0);
724 767
725 } // endif: observation pointer was valid 768 } // endif: observation pointer was valid
726 769
@@ -740,11 +783,15 @@ void ctobssim::simulate_source(GCTAObservation* obs, const GModels&amp; models) @@ -740,11 +783,15 @@ void ctobssim::simulate_source(GCTAObservation* obs, const GModels&amp; models)
740 * 783 *
741 * This method does nothing if the observation pointer is NULL. 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 // Continue only if observation pointer is valid 788 // Continue only if observation pointer is valid
746 if (obs != NULL) { 789 if (obs != NULL) {
747 790
  791 + if(wrklog==NULL){
  792 + wrklog=&log;
  793 + }
  794 +
748 // Make sure that the observation holds a CTA event list. If this 795 // Make sure that the observation holds a CTA event list. If this
749 // is not the case then allocate and attach a CTA event list now. 796 // is not the case then allocate and attach a CTA event list now.
750 if (dynamic_cast<const GCTAEventList*>(obs->events()) == NULL) { 797 if (dynamic_cast<const GCTAEventList*>(obs->events()) == NULL) {
@@ -766,7 +813,7 @@ void ctobssim::simulate_background(GCTAObservation* obs, const GModels&amp; models) @@ -766,7 +813,7 @@ void ctobssim::simulate_background(GCTAObservation* obs, const GModels&amp; models)
766 813
767 // Get simulated event list. Note that this method includes 814 // Get simulated event list. Note that this method includes
768 // the deadtime correction. 815 // the deadtime correction.
769 - GCTAEventList* list = model->mc(*obs, m_ran); 816 + GCTAEventList* list = model->mc(*obs, ran);
770 817
771 // Reserves space for events 818 // Reserves space for events
772 events->reserve(list->size()+events->size()); 819 events->reserve(list->size()+events->size());
@@ -784,8 +831,8 @@ void ctobssim::simulate_background(GCTAObservation* obs, const GModels&amp; models) @@ -784,8 +831,8 @@ void ctobssim::simulate_background(GCTAObservation* obs, const GModels&amp; models)
784 831
785 // Dump simulation results 832 // Dump simulation results
786 if (logNormal()) { 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 // Free event list 838 // Free event list
@@ -875,7 +922,7 @@ void ctobssim::copy_members(const ctobssim&amp; app) @@ -875,7 +922,7 @@ void ctobssim::copy_members(const ctobssim&amp; app)
875 // Copy protected members 922 // Copy protected members
876 m_area = app.m_area; 923 m_area = app.m_area;
877 m_time_max = app.m_time_max; 924 m_time_max = app.m_time_max;
878 - m_ran = app.m_ran; 925 + m_rans = app.m_rans;
879 m_obs = app.m_obs; 926 m_obs = app.m_obs;
880 m_use_xml = app.m_use_xml; 927 m_use_xml = app.m_use_xml;
881 m_read_ahead = app.m_read_ahead; 928 m_read_ahead = app.m_read_ahead;
src/ctobssim/ctobssim.hpp
@@ -67,8 +67,8 @@ public: @@ -67,8 +67,8 @@ public:
67 GObservations& obs(void) { return m_obs; } 67 GObservations& obs(void) { return m_obs; }
68 void get_parameters(void); 68 void get_parameters(void);
69 void set_list(GCTAObservation* obs); 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 protected: 73 protected:
74 // Protected methods 74 // Protected methods
@@ -97,7 +97,8 @@ protected: @@ -97,7 +97,8 @@ protected:
97 // Protected members 97 // Protected members
98 double m_area; //!< Surface area for simulation (cm2) 98 double m_area; //!< Surface area for simulation (cm2)
99 GTime m_time_max; //!< Maximum length of time slice (sec) 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 GObservations m_obs; //!< Observation container 102 GObservations m_obs; //!< Observation container
102 bool m_use_xml; //!< Use XML file instead of FITS file 103 bool m_use_xml; //!< Use XML file instead of FITS file
103 bool m_read_ahead; //!< Read ahead parameters 104 bool m_read_ahead; //!< Read ahead parameters