Commit 0823df67dde6bf48490a7050f6b21b2194bba422
Merge branch 'integration' into devel
Showing
5 changed files
with
82 additions
and
30 deletions
ChangeLog
| 1 | -2017-07-27 | |
| 1 | +2017-07-28 | |
| 2 | 2 | |
| 3 | 3 | * Version 1.4.0 released |
| 4 | 4 | ======================== |
| 5 | 5 | |
| 6 | 6 | Fix ctmodel bug for stacked analysis with diffuse maps or cubes (#2171) |
| 7 | 7 | Install ctools header files (#2145) |
| 8 | + Parallelize event binning in ctbin using OpenMP (#1970) | |
| 8 | 9 | |
| 9 | 10 | |
| 10 | 11 | 2017-07-07 | ... | ... |
NEWS
| 1 | 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 | 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
| ... | ... | @@ -25,6 +25,8 @@ Improvements |
| 25 | 25 | Fix ctmodel bug for stacked analysis with diffuse maps or cubes |
| 26 | 26 | * [`2145 <https://cta-redmine.irap.omp.eu/issues/2145>`_] - |
| 27 | 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 | 32 | New features | ... | ... |
src/ctbin/ctbin.cpp
| ... | ... | @@ -233,11 +233,32 @@ 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", | |
| 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 | 254 | log_header1(TERSE, gammalib::number("Bin observation", m_obs.size())); |
| 237 | 255 | |
| 238 | 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 | 263 | // Fill the cube |
| 243 | 264 | fill_cube(obs); |
| ... | ... | @@ -361,6 +382,9 @@ void ctbin::init_members(void) |
| 361 | 382 | m_ontime = 0.0; |
| 362 | 383 | m_livetime = 0.0; |
| 363 | 384 | |
| 385 | + // Initialise cache members | |
| 386 | + m_dirs.clear(); | |
| 387 | + | |
| 364 | 388 | // Set CTA reference time |
| 365 | 389 | m_gti.reference(m_cta_ref); |
| 366 | 390 | |
| ... | ... | @@ -383,13 +407,16 @@ void ctbin::copy_members(const ctbin& app) |
| 383 | 407 | m_chatter = app.m_chatter; |
| 384 | 408 | |
| 385 | 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 | 421 | // Return |
| 395 | 422 | return; |
| ... | ... | @@ -443,6 +470,13 @@ void ctbin::get_parameters(void) |
| 443 | 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 | 480 | // Write parameters into logger |
| 447 | 481 | log_parameters(TERSE); |
| 448 | 482 | |
| ... | ... | @@ -503,8 +537,8 @@ void ctbin::fill_cube(GCTAObservation* obs) |
| 503 | 537 | const GCTAEventAtom* event = (*events)[i]; |
| 504 | 538 | |
| 505 | 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 | 543 | // Skip event if it is outside the RoI |
| 510 | 544 | if (roi.centre().dir().dist_deg(dir) > roi.radius()) { |
| ... | ... | @@ -542,25 +576,36 @@ void ctbin::fill_cube(GCTAObservation* obs) |
| 542 | 576 | } |
| 543 | 577 | |
| 544 | 578 | // Fill event in skymap |
| 579 | + #pragma omp critical(ctbin_fill_cube) | |
| 545 | 580 | m_counts(pixel, iebin) += 1.0; |
| 581 | + | |
| 582 | + // Increment number of maps | |
| 546 | 583 | num_in_map++; |
| 547 | 584 | |
| 548 | 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 | 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 | 610 | // Return |
| 566 | 611 | return; |
| ... | ... | @@ -609,11 +654,8 @@ void ctbin::set_weights(GCTAObservation* obs) |
| 609 | 654 | // Loop over all pixels in counts cube |
| 610 | 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 | 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 | 659 | continue; |
| 618 | 660 | } |
| 619 | 661 | |
| ... | ... | @@ -624,7 +666,9 @@ void ctbin::set_weights(GCTAObservation* obs) |
| 624 | 666 | if (!usage[iebin]) { |
| 625 | 667 | continue; |
| 626 | 668 | } |
| 669 | + | |
| 627 | 670 | // Signal that bin was filled |
| 671 | + #pragma omp critical(ctbin_set_weights) | |
| 628 | 672 | m_weights(pixel, iebin) = 1.0; |
| 629 | 673 | |
| 630 | 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,6 +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 | + | |
| 106 | + // Cache members | |
| 107 | + std::vector<GSkyDir> m_dirs; //!< Cached GSkyDir for each pixel in m_counts | |
| 105 | 108 | }; |
| 106 | 109 | |
| 107 | 110 | ... | ... |