Commit 6b5fac3ee761668209bc5b84c268da15b70f226b

Authored by Jürgen Knödlseder
1 parent 75bde4e8

Integrate code

ChangeLog
1   -2017-07-03
  1 +2017-07-28
2 2  
3 3 * Version 1.4.0 released
4 4 ========================
5 5  
6 6 Install ctools header files (#2145)
  7 + Parallelize event binning in ctbin using OpenMP (#1970)
7 8  
8 9  
9 10 2017-06-23
... ...
1 1 New Features and Important Changes in ctools 1.4.0
2 2  
3   -3 July 2017
  3 +28 July 2017
4 4  
5 5  
6 6 Introduction
... ... @@ -37,7 +37,9 @@ None
37 37  
38 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 45 ctlike - Maximum likelihood fitting
... ...
doc/source/admin/release_history/1.4.rst
... ... @@ -23,6 +23,8 @@ Improvements
23 23  
24 24 * [`2145 <https://cta-redmine.irap.omp.eu/issues/2145>`_] -
25 25 Install C++ header files
  26 +* [`1970 <https://cta-redmine.irap.omp.eu/issues/1970>`_] -
  27 + Parallelize :ref:`ctbin` using OpenMP
26 28  
27 29  
28 30 New features
... ...
src/ctbin/ctbin.cpp
... ... @@ -233,25 +233,33 @@ void ctbin::run(void)
233 233 log_observations(NORMAL, m_obs, "Input observation");
234 234  
235 235 // Write header into logger
236   - log_header1(TERSE, gammalib::number("Find unbinned observation", m_obs.size()));
  236 + log_header1(TERSE, gammalib::number("Find unbinned observation",
  237 + m_obs.size()));
237 238  
238 239 // Find all unbinned CTA observations in m_obs
239 240 std::vector<GCTAObservation*> obs_list(0);
240 241 for (GCTAObservation* obs = first_unbinned_observation(); obs != NULL;
241 242 obs = next_unbinned_observation()) {
242   - std::string msg = " Including unbinned "+obs->instrument()+" observation";
243   - log_string(NORMAL, msg);
  243 +
  244 + // Push observation into list
244 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);
245 251 }
246 252  
247 253 // Write header into logger
248 254 log_header1(TERSE, gammalib::number("Bin observation", m_obs.size()));
249   -
  255 +
250 256 // Loop over all unbinned CTA observations in the container
251   - #pragma omp parallel for
252   - for (int oindx=0; oindx<obs_list.size(); ++oindx) {
253   - GCTAObservation* obs = obs_list[oindx];
254   -
  257 + #pragma omp parallel for(ctbin_run)
  258 + for (int i = 0; i < obs_list.size(); ++i) {
  259 +
  260 + // Get pointer to observation
  261 + GCTAObservation* obs = obs_list[i];
  262 +
255 263 // Fill the cube
256 264 fill_cube(obs);
257 265  
... ... @@ -371,10 +379,12 @@ void ctbin::init_members(void)
371 379 m_ebounds.clear();
372 380 m_gti.clear();
373 381 m_cube.clear();
374   - m_dirs.clear();
375 382 m_ontime = 0.0;
376 383 m_livetime = 0.0;
377 384  
  385 + // Initialise cache members
  386 + m_dirs.clear();
  387 +
378 388 // Set CTA reference time
379 389 m_gti.reference(m_cta_ref);
380 390  
... ... @@ -397,14 +407,16 @@ void ctbin::copy_members(const ctbin&amp; app)
397 407 m_chatter = app.m_chatter;
398 408  
399 409 // Copy protected members
400   - m_counts = app.m_counts;
401   - m_weights = app.m_weights;
402   - m_ebounds = app.m_ebounds;
403   - m_gti = app.m_gti;
404   - m_cube = app.m_cube;
405   - m_dirs = app.m_dirs;
406   - m_ontime = app.m_ontime;
407   - 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;
408 420  
409 421 // Return
410 422 return;
... ... @@ -445,13 +457,6 @@ void ctbin::get_parameters(void)
445 457 m_counts = 0.0;
446 458 m_weights = m_counts;
447 459  
448   - // Cache sky directions in m_counts
449   - m_dirs.resize(m_counts.npix());
450   - for (int pix=0; pix<m_counts.npix(); pix++) {
451   - m_dirs[pix] = m_counts.inx2dir(pix);
452   - m_dirs[pix].radec(m_dirs[pix].ra(), m_dirs[pix].dec());
453   - }
454   -
455 460 // Get energy boundaries
456 461 m_ebounds = cube.ebounds();
457 462  
... ... @@ -465,6 +470,13 @@ void ctbin::get_parameters(void)
465 470 m_outcube = (*this)["outcube"].filename();
466 471 }
467 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 +
468 480 // Write parameters into logger
469 481 log_parameters(TERSE);
470 482  
... ... @@ -525,8 +537,8 @@ void ctbin::fill_cube(GCTAObservation* obs)
525 537 const GCTAEventAtom* event = (*events)[i];
526 538  
527 539 // Determine event sky direction
528   - GCTAInstDir* inst = (GCTAInstDir*)&(event->dir());
529   - GSkyDir dir = inst->dir();
  540 + GCTAInstDir* inst = (GCTAInstDir*)&(event->dir());
  541 + GSkyDir dir = inst->dir();
530 542  
531 543 // Skip event if it is outside the RoI
532 544 if (roi.centre().dir().dist_deg(dir) > roi.radius()) {
... ... @@ -564,32 +576,37 @@ void ctbin::fill_cube(GCTAObservation* obs)
564 576 }
565 577  
566 578 // Fill event in skymap
567   - #pragma omp critical
  579 + #pragma omp critical(ctbin_fill_cube)
568 580 m_counts(pixel, iebin) += 1.0;
569   -
  581 +
  582 + // Increment number of maps
570 583 num_in_map++;
571 584  
572 585 } // endfor: looped over all events
573 586  
574   - #pragma omp critical
  587 + // Update time information
  588 + #pragma omp critical(ctbin_fill_cube)
575 589 {
576 590 // Append GTIs
577 591 m_gti.extend(events->gti());
578   -
  592 +
579 593 // Update ontime and livetime
580 594 m_ontime += obs->ontime();
581 595 m_livetime += obs->livetime();
582 596 }
583   -
  597 +
584 598 // Log filling results
585   - log_header3(TERSE, get_obs_header(obs));
586   - log_value(NORMAL, "Events in list", obs->events()->size());
587   - log_value(NORMAL, "Events in cube", num_in_map);
588   - log_value(NORMAL, "Events outside RoI", num_outside_roi);
589   - log_value(NORMAL, "Events with invalid WCS", num_invalid_wcs);
590   - log_value(NORMAL, "Events outside cube area", num_outside_map);
591   - log_value(NORMAL, "Events outside energy bins", num_outside_ebds);
592   -
  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 + }
  609 +
593 610 // Return
594 611 return;
595 612 }
... ... @@ -636,7 +653,7 @@ void ctbin::set_weights(GCTAObservation* obs)
636 653  
637 654 // Loop over all pixels in counts cube
638 655 for (int pixel = 0; pixel < m_counts.npix(); ++pixel) {
639   -
  656 +
640 657 // Skip pixel if it is outside the RoI
641 658 if (roi.centre().dir().dist_deg(m_dirs[pixel]) > roi.radius()) {
642 659 continue;
... ... @@ -649,7 +666,9 @@ void ctbin::set_weights(GCTAObservation* obs)
649 666 if (!usage[iebin]) {
650 667 continue;
651 668 }
  669 +
652 670 // Signal that bin was filled
  671 + #pragma omp critical(ctbin_set_weights)
653 672 m_weights(pixel, iebin) = 1.0;
654 673  
655 674 } // endfor: looped over energy layers of counts cube
... ...
src/ctbin/ctbin.hpp
1 1 /***************************************************************************
2 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 7 * This program is free software: you can redistribute it and/or modify *
... ... @@ -102,7 +102,9 @@ protected:
102 102 GCTAEventCube m_cube; //!< Events cube (for cube() method)
103 103 double m_ontime; //!< Total ontime
104 104 double m_livetime; //!< Total livetime
105   - std::vector<GSkyDir> m_dirs; //!< Cached GSkyDir for each pixel in m_counts
  105 +
  106 + // Cache members
  107 + std::vector<GSkyDir> m_dirs; //!< Cached GSkyDir for each pixel in m_counts
106 108 };
107 109  
108 110  
... ...