Commit 0823df67dde6bf48490a7050f6b21b2194bba422

Authored by Jürgen Knödlseder
2 parents 624999d9 36b7c210

Merge branch 'integration' into devel

ChangeLog
1 -2017-07-27 1 +2017-07-28
2 2
3 * Version 1.4.0 released 3 * Version 1.4.0 released
4 ======================== 4 ========================
5 5
6 Fix ctmodel bug for stacked analysis with diffuse maps or cubes (#2171) 6 Fix ctmodel bug for stacked analysis with diffuse maps or cubes (#2171)
7 Install ctools header files (#2145) 7 Install ctools header files (#2145)
  8 + Parallelize event binning in ctbin using OpenMP (#1970)
8 9
9 10
10 2017-07-07 11 2017-07-07
1 New Features and Important Changes in ctools 1.4.0 1 New Features and Important Changes in ctools 1.4.0
2 2
3 -27 July 2017 3 +28 July 2017
4 4
5 5
6 Introduction 6 Introduction
@@ -37,7 +37,9 @@ None @@ -37,7 +37,9 @@ None
37 37
38 ctbin - CTA event binning 38 ctbin - CTA event binning
39 ------------------------- 39 -------------------------
40 -None 40 +The loop over the observations was parallelized using OpenMP for faster
  41 +execution. In addition, the sky directions were cached for faster computation
  42 +of the weights (#1970).
41 43
42 44
43 ctlike - Maximum likelihood fitting 45 ctlike - Maximum likelihood fitting
doc/source/admin/release_history/1.4.rst
@@ -25,6 +25,8 @@ Improvements @@ -25,6 +25,8 @@ Improvements
25 Fix ctmodel bug for stacked analysis with diffuse maps or cubes 25 Fix ctmodel bug for stacked analysis with diffuse maps or cubes
26 * [`2145 <https://cta-redmine.irap.omp.eu/issues/2145>`_] - 26 * [`2145 <https://cta-redmine.irap.omp.eu/issues/2145>`_] -
27 Install C++ header files 27 Install C++ header files
  28 +* [`1970 <https://cta-redmine.irap.omp.eu/issues/1970>`_] -
  29 + Parallelize :ref:`ctbin` using OpenMP
28 30
29 31
30 New features 32 New features
src/ctbin/ctbin.cpp
@@ -233,11 +233,32 @@ void ctbin::run(void) @@ -233,11 +233,32 @@ void ctbin::run(void)
233 log_observations(NORMAL, m_obs, "Input observation"); 233 log_observations(NORMAL, m_obs, "Input observation");
234 234
235 // Write header into logger 235 // Write header into logger
  236 + log_header1(TERSE, gammalib::number("Find unbinned observation",
  237 + m_obs.size()));
  238 +
  239 + // Find all unbinned CTA observations in m_obs
  240 + std::vector<GCTAObservation*> obs_list(0);
  241 + for (GCTAObservation* obs = first_unbinned_observation(); obs != NULL;
  242 + obs = next_unbinned_observation()) {
  243 +
  244 + // Push observation into list
  245 + obs_list.push_back(obs);
  246 +
  247 + // Write message
  248 + std::string msg = " Including unbinned "+obs->instrument()+
  249 + " observation";
  250 + log_string(NORMAL, msg);
  251 + }
  252 +
  253 + // Write header into logger
236 log_header1(TERSE, gammalib::number("Bin observation", m_obs.size())); 254 log_header1(TERSE, gammalib::number("Bin observation", m_obs.size()));
237 255
238 // Loop over all unbinned CTA observations in the container 256 // Loop over all unbinned CTA observations in the container
239 - for (GCTAObservation* obs = first_unbinned_observation(); obs != NULL;  
240 - obs = next_unbinned_observation()) { 257 + #pragma omp parallel for
  258 + for (int i = 0; i < obs_list.size(); ++i) {
  259 +
  260 + // Get pointer to observation
  261 + GCTAObservation* obs = obs_list[i];
241 262
242 // Fill the cube 263 // Fill the cube
243 fill_cube(obs); 264 fill_cube(obs);
@@ -361,6 +382,9 @@ void ctbin::init_members(void) @@ -361,6 +382,9 @@ void ctbin::init_members(void)
361 m_ontime = 0.0; 382 m_ontime = 0.0;
362 m_livetime = 0.0; 383 m_livetime = 0.0;
363 384
  385 + // Initialise cache members
  386 + m_dirs.clear();
  387 +
364 // Set CTA reference time 388 // Set CTA reference time
365 m_gti.reference(m_cta_ref); 389 m_gti.reference(m_cta_ref);
366 390
@@ -383,13 +407,16 @@ void ctbin::copy_members(const ctbin&amp; app) @@ -383,13 +407,16 @@ void ctbin::copy_members(const ctbin&amp; app)
383 m_chatter = app.m_chatter; 407 m_chatter = app.m_chatter;
384 408
385 // Copy protected members 409 // Copy protected members
386 - m_counts = app.m_counts;  
387 - m_weights = app.m_weights;  
388 - m_ebounds = app.m_ebounds;  
389 - m_gti = app.m_gti;  
390 - m_cube = app.m_cube;  
391 - m_ontime = app.m_ontime;  
392 - m_livetime = app.m_livetime; 410 + m_counts = app.m_counts;
  411 + m_weights = app.m_weights;
  412 + m_ebounds = app.m_ebounds;
  413 + m_gti = app.m_gti;
  414 + m_cube = app.m_cube;
  415 + m_ontime = app.m_ontime;
  416 + m_livetime = app.m_livetime;
  417 +
  418 + // Copy cache members
  419 + m_dirs = app.m_dirs;
393 420
394 // Return 421 // Return
395 return; 422 return;
@@ -443,6 +470,13 @@ void ctbin::get_parameters(void) @@ -443,6 +470,13 @@ void ctbin::get_parameters(void)
443 m_outcube = (*this)["outcube"].filename(); 470 m_outcube = (*this)["outcube"].filename();
444 } 471 }
445 472
  473 + // Cache sky directions in m_counts
  474 + m_dirs.resize(m_counts.npix());
  475 + for (int pix = 0; pix < m_counts.npix(); ++pix) {
  476 + m_dirs[pix] = m_counts.inx2dir(pix);
  477 + m_dirs[pix].radec(m_dirs[pix].ra(), m_dirs[pix].dec());
  478 + }
  479 +
446 // Write parameters into logger 480 // Write parameters into logger
447 log_parameters(TERSE); 481 log_parameters(TERSE);
448 482
@@ -503,8 +537,8 @@ void ctbin::fill_cube(GCTAObservation* obs) @@ -503,8 +537,8 @@ void ctbin::fill_cube(GCTAObservation* obs)
503 const GCTAEventAtom* event = (*events)[i]; 537 const GCTAEventAtom* event = (*events)[i];
504 538
505 // Determine event sky direction 539 // Determine event sky direction
506 - GCTAInstDir* inst = (GCTAInstDir*)&(event->dir());  
507 - GSkyDir dir = inst->dir(); 540 + GCTAInstDir* inst = (GCTAInstDir*)&(event->dir());
  541 + GSkyDir dir = inst->dir();
508 542
509 // Skip event if it is outside the RoI 543 // Skip event if it is outside the RoI
510 if (roi.centre().dir().dist_deg(dir) > roi.radius()) { 544 if (roi.centre().dir().dist_deg(dir) > roi.radius()) {
@@ -542,25 +576,36 @@ void ctbin::fill_cube(GCTAObservation* obs) @@ -542,25 +576,36 @@ void ctbin::fill_cube(GCTAObservation* obs)
542 } 576 }
543 577
544 // Fill event in skymap 578 // Fill event in skymap
  579 + #pragma omp critical(ctbin_fill_cube)
545 m_counts(pixel, iebin) += 1.0; 580 m_counts(pixel, iebin) += 1.0;
  581 +
  582 + // Increment number of maps
546 num_in_map++; 583 num_in_map++;
547 584
548 } // endfor: looped over all events 585 } // endfor: looped over all events
549 586
550 - // Append GTIs  
551 - m_gti.extend(events->gti()); 587 + // Update time information
  588 + #pragma omp critical(ctbin_fill_cube)
  589 + {
  590 + // Append GTIs
  591 + m_gti.extend(events->gti());
552 592
553 - // Update ontime and livetime  
554 - m_ontime += obs->ontime();  
555 - m_livetime += obs->livetime(); 593 + // Update ontime and livetime
  594 + m_ontime += obs->ontime();
  595 + m_livetime += obs->livetime();
  596 + }
556 597
557 // Log filling results 598 // Log filling results
558 - log_value(NORMAL, "Events in list", obs->events()->size());  
559 - log_value(NORMAL, "Events in cube", num_in_map);  
560 - log_value(NORMAL, "Events outside RoI", num_outside_roi);  
561 - log_value(NORMAL, "Events with invalid WCS", num_invalid_wcs);  
562 - log_value(NORMAL, "Events outside cube area", num_outside_map);  
563 - log_value(NORMAL, "Events outside energy bins", num_outside_ebds); 599 + #pragma omp critical(ctbin_fill_cube)
  600 + {
  601 + log_header3(TERSE, get_obs_header(obs));
  602 + log_value(NORMAL, "Events in list", obs->events()->size());
  603 + log_value(NORMAL, "Events in cube", num_in_map);
  604 + log_value(NORMAL, "Events outside RoI", num_outside_roi);
  605 + log_value(NORMAL, "Events with invalid WCS", num_invalid_wcs);
  606 + log_value(NORMAL, "Events outside cube area", num_outside_map);
  607 + log_value(NORMAL, "Events outside energy bins", num_outside_ebds);
  608 + }
564 609
565 // Return 610 // Return
566 return; 611 return;
@@ -609,11 +654,8 @@ void ctbin::set_weights(GCTAObservation* obs) @@ -609,11 +654,8 @@ void ctbin::set_weights(GCTAObservation* obs)
609 // Loop over all pixels in counts cube 654 // Loop over all pixels in counts cube
610 for (int pixel = 0; pixel < m_counts.npix(); ++pixel) { 655 for (int pixel = 0; pixel < m_counts.npix(); ++pixel) {
611 656
612 - // Get pixel sky direction  
613 - GSkyDir dir = m_counts.inx2dir(pixel);  
614 -  
615 // Skip pixel if it is outside the RoI 657 // Skip pixel if it is outside the RoI
616 - if (roi.centre().dir().dist_deg(dir) > roi.radius()) { 658 + if (roi.centre().dir().dist_deg(m_dirs[pixel]) > roi.radius()) {
617 continue; 659 continue;
618 } 660 }
619 661
@@ -624,7 +666,9 @@ void ctbin::set_weights(GCTAObservation* obs) @@ -624,7 +666,9 @@ void ctbin::set_weights(GCTAObservation* obs)
624 if (!usage[iebin]) { 666 if (!usage[iebin]) {
625 continue; 667 continue;
626 } 668 }
  669 +
627 // Signal that bin was filled 670 // Signal that bin was filled
  671 + #pragma omp critical(ctbin_set_weights)
628 m_weights(pixel, iebin) = 1.0; 672 m_weights(pixel, iebin) = 1.0;
629 673
630 } // endfor: looped over energy layers of counts cube 674 } // endfor: looped over energy layers of counts cube
src/ctbin/ctbin.hpp
1 /*************************************************************************** 1 /***************************************************************************
2 * ctbin - Event binning tool * 2 * ctbin - Event binning tool *
3 * ----------------------------------------------------------------------- * 3 * ----------------------------------------------------------------------- *
4 - * copyright (C) 2010-2016 by Juergen Knoedlseder * 4 + * copyright (C) 2010-2017 by Juergen Knoedlseder *
5 * ----------------------------------------------------------------------- * 5 * ----------------------------------------------------------------------- *
6 * * 6 * *
7 * This program is free software: you can redistribute it and/or modify * 7 * This program is free software: you can redistribute it and/or modify *
@@ -102,6 +102,9 @@ protected: @@ -102,6 +102,9 @@ protected:
102 GCTAEventCube m_cube; //!< Events cube (for cube() method) 102 GCTAEventCube m_cube; //!< Events cube (for cube() method)
103 double m_ontime; //!< Total ontime 103 double m_ontime; //!< Total ontime
104 double m_livetime; //!< Total livetime 104 double m_livetime; //!< Total livetime
  105 +
  106 + // Cache members
  107 + std::vector<GSkyDir> m_dirs; //!< Cached GSkyDir for each pixel in m_counts
105 }; 108 };
106 109
107 110