Commit 6b5fac3ee761668209bc5b84c268da15b70f226b
1 parent
75bde4e8
Integrate code
Showing
5 changed files
with
71 additions
and
45 deletions
ChangeLog
| 1 | -2017-07-03 | 1 | +2017-07-28 |
| 2 | 2 | ||
| 3 | * Version 1.4.0 released | 3 | * Version 1.4.0 released |
| 4 | ======================== | 4 | ======================== |
| 5 | 5 | ||
| 6 | Install ctools header files (#2145) | 6 | Install ctools header files (#2145) |
| 7 | + Parallelize event binning in ctbin using OpenMP (#1970) | ||
| 7 | 8 | ||
| 8 | 9 | ||
| 9 | 2017-06-23 | 10 | 2017-06-23 |
NEWS
| 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 | -3 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
| @@ -23,6 +23,8 @@ Improvements | @@ -23,6 +23,8 @@ Improvements | ||
| 23 | 23 | ||
| 24 | * [`2145 <https://cta-redmine.irap.omp.eu/issues/2145>`_] - | 24 | * [`2145 <https://cta-redmine.irap.omp.eu/issues/2145>`_] - |
| 25 | Install C++ header files | 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 | New features | 30 | New features |
src/ctbin/ctbin.cpp
| @@ -233,25 +233,33 @@ void ctbin::run(void) | @@ -233,25 +233,33 @@ 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", m_obs.size())); | 236 | + log_header1(TERSE, gammalib::number("Find unbinned observation", |
| 237 | + m_obs.size())); | ||
| 237 | 238 | ||
| 238 | // Find all unbinned CTA observations in m_obs | 239 | // Find all unbinned CTA observations in m_obs |
| 239 | std::vector<GCTAObservation*> obs_list(0); | 240 | std::vector<GCTAObservation*> obs_list(0); |
| 240 | for (GCTAObservation* obs = first_unbinned_observation(); obs != NULL; | 241 | for (GCTAObservation* obs = first_unbinned_observation(); obs != NULL; |
| 241 | obs = next_unbinned_observation()) { | 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 | obs_list.push_back(obs); | 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 | // Write header into logger | 253 | // Write header into logger |
| 248 | log_header1(TERSE, gammalib::number("Bin observation", m_obs.size())); | 254 | log_header1(TERSE, gammalib::number("Bin observation", m_obs.size())); |
| 249 | - | 255 | + |
| 250 | // Loop over all unbinned CTA observations in the container | 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 | // Fill the cube | 263 | // Fill the cube |
| 256 | fill_cube(obs); | 264 | fill_cube(obs); |
| 257 | 265 | ||
| @@ -371,10 +379,12 @@ void ctbin::init_members(void) | @@ -371,10 +379,12 @@ void ctbin::init_members(void) | ||
| 371 | m_ebounds.clear(); | 379 | m_ebounds.clear(); |
| 372 | m_gti.clear(); | 380 | m_gti.clear(); |
| 373 | m_cube.clear(); | 381 | m_cube.clear(); |
| 374 | - m_dirs.clear(); | ||
| 375 | m_ontime = 0.0; | 382 | m_ontime = 0.0; |
| 376 | m_livetime = 0.0; | 383 | m_livetime = 0.0; |
| 377 | 384 | ||
| 385 | + // Initialise cache members | ||
| 386 | + m_dirs.clear(); | ||
| 387 | + | ||
| 378 | // Set CTA reference time | 388 | // Set CTA reference time |
| 379 | m_gti.reference(m_cta_ref); | 389 | m_gti.reference(m_cta_ref); |
| 380 | 390 | ||
| @@ -397,14 +407,16 @@ void ctbin::copy_members(const ctbin& app) | @@ -397,14 +407,16 @@ void ctbin::copy_members(const ctbin& app) | ||
| 397 | m_chatter = app.m_chatter; | 407 | m_chatter = app.m_chatter; |
| 398 | 408 | ||
| 399 | // Copy protected members | 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 | // Return | 421 | // Return |
| 410 | return; | 422 | return; |
| @@ -445,13 +457,6 @@ void ctbin::get_parameters(void) | @@ -445,13 +457,6 @@ void ctbin::get_parameters(void) | ||
| 445 | m_counts = 0.0; | 457 | m_counts = 0.0; |
| 446 | m_weights = m_counts; | 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 | // Get energy boundaries | 460 | // Get energy boundaries |
| 456 | m_ebounds = cube.ebounds(); | 461 | m_ebounds = cube.ebounds(); |
| 457 | 462 | ||
| @@ -465,6 +470,13 @@ void ctbin::get_parameters(void) | @@ -465,6 +470,13 @@ void ctbin::get_parameters(void) | ||
| 465 | m_outcube = (*this)["outcube"].filename(); | 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 | // Write parameters into logger | 480 | // Write parameters into logger |
| 469 | log_parameters(TERSE); | 481 | log_parameters(TERSE); |
| 470 | 482 | ||
| @@ -525,8 +537,8 @@ void ctbin::fill_cube(GCTAObservation* obs) | @@ -525,8 +537,8 @@ void ctbin::fill_cube(GCTAObservation* obs) | ||
| 525 | const GCTAEventAtom* event = (*events)[i]; | 537 | const GCTAEventAtom* event = (*events)[i]; |
| 526 | 538 | ||
| 527 | // Determine event sky direction | 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 | // Skip event if it is outside the RoI | 543 | // Skip event if it is outside the RoI |
| 532 | if (roi.centre().dir().dist_deg(dir) > roi.radius()) { | 544 | if (roi.centre().dir().dist_deg(dir) > roi.radius()) { |
| @@ -564,32 +576,37 @@ void ctbin::fill_cube(GCTAObservation* obs) | @@ -564,32 +576,37 @@ void ctbin::fill_cube(GCTAObservation* obs) | ||
| 564 | } | 576 | } |
| 565 | 577 | ||
| 566 | // Fill event in skymap | 578 | // Fill event in skymap |
| 567 | - #pragma omp critical | 579 | + #pragma omp critical(ctbin_fill_cube) |
| 568 | m_counts(pixel, iebin) += 1.0; | 580 | m_counts(pixel, iebin) += 1.0; |
| 569 | - | 581 | + |
| 582 | + // Increment number of maps | ||
| 570 | num_in_map++; | 583 | num_in_map++; |
| 571 | 584 | ||
| 572 | } // endfor: looped over all events | 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 | // Append GTIs | 590 | // Append GTIs |
| 577 | m_gti.extend(events->gti()); | 591 | m_gti.extend(events->gti()); |
| 578 | - | 592 | + |
| 579 | // Update ontime and livetime | 593 | // Update ontime and livetime |
| 580 | m_ontime += obs->ontime(); | 594 | m_ontime += obs->ontime(); |
| 581 | m_livetime += obs->livetime(); | 595 | m_livetime += obs->livetime(); |
| 582 | } | 596 | } |
| 583 | - | 597 | + |
| 584 | // Log filling results | 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 | // Return | 610 | // Return |
| 594 | return; | 611 | return; |
| 595 | } | 612 | } |
| @@ -636,7 +653,7 @@ void ctbin::set_weights(GCTAObservation* obs) | @@ -636,7 +653,7 @@ void ctbin::set_weights(GCTAObservation* obs) | ||
| 636 | 653 | ||
| 637 | // Loop over all pixels in counts cube | 654 | // Loop over all pixels in counts cube |
| 638 | for (int pixel = 0; pixel < m_counts.npix(); ++pixel) { | 655 | for (int pixel = 0; pixel < m_counts.npix(); ++pixel) { |
| 639 | - | 656 | + |
| 640 | // Skip pixel if it is outside the RoI | 657 | // Skip pixel if it is outside the RoI |
| 641 | if (roi.centre().dir().dist_deg(m_dirs[pixel]) > roi.radius()) { | 658 | if (roi.centre().dir().dist_deg(m_dirs[pixel]) > roi.radius()) { |
| 642 | continue; | 659 | continue; |
| @@ -649,7 +666,9 @@ void ctbin::set_weights(GCTAObservation* obs) | @@ -649,7 +666,9 @@ void ctbin::set_weights(GCTAObservation* obs) | ||
| 649 | if (!usage[iebin]) { | 666 | if (!usage[iebin]) { |
| 650 | continue; | 667 | continue; |
| 651 | } | 668 | } |
| 669 | + | ||
| 652 | // Signal that bin was filled | 670 | // Signal that bin was filled |
| 671 | + #pragma omp critical(ctbin_set_weights) | ||
| 653 | m_weights(pixel, iebin) = 1.0; | 672 | m_weights(pixel, iebin) = 1.0; |
| 654 | 673 | ||
| 655 | } // 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,7 +102,9 @@ protected: | @@ -102,7 +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 | - 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 |