Skip to content

Commit ff6efa2

Browse files
Merge pull request #554 from teeteg/fast_secondaries
fix and enhancement to secondary propagation in ModuleList
2 parents 244f704 + b117732 commit ff6efa2

3 files changed

Lines changed: 41 additions & 18 deletions

File tree

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
## CRPropa vNext
22

33
### Bug fixes:
4+
* Fixed the secondariesFirst parameter not actually allowing secondary particles to be propagated before the primary
45
* threshold calculation in PhotoPionProduction
56

67
### New features:
78

89
* Improved plugin-template and added test to ensure the template is working
10+
* Secondaries are now distributed over multiple threads if OpenMP parallelisation is enabled
911

1012
### Interface changes:
1113

include/crpropa/ModuleList.h

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -82,40 +82,48 @@ class ModuleList: public Module {
8282
* @param recursive Whether to also process possible created secondaries
8383
* @param secondariesFirst Whether to process the secondaries directly after the
8484
* step where they are created or to only process them after the primary is fully finished
85+
* @param waitForSecondaries Whether to wait for the secondaries to be fully processed
86+
* before continuing with the primary candidate if secondariesFirst is set to true
8587
*/
86-
void run(Candidate* candidate, bool recursive = true, bool secondariesFirst = true);
88+
void run(Candidate* candidate, bool recursive = true, bool secondariesFirst = true, bool waitForSecondaries = true);
8789
/** Run function
8890
* This function wrapps the ModuleList::run(Candidate* candidate) function
8991
* This run function does the full simulation for a single given candidate
9092
* @param candidate Candidate to use for the simulation
9193
* @param recursive Whether to also process possible created secondaries
9294
* @param secondariesFirst Whether to process the secondaries directly after the
9395
* step where they are created or to only process them after the primary is fully finished
96+
* @param waitForSecondaries Whether to wait for the secondaries to be fully processed
97+
* before continuing with the primary candidate if secondariesFirst is set to true
9498
*/
95-
void run(ref_ptr<Candidate> candidate, bool recursive = true, bool secondariesFirst = true);
99+
void run(ref_ptr<Candidate> candidate, bool recursive = true, bool secondariesFirst = true, bool waitForSecondaries = true);
96100
/** Run function
97101
* This function calls the run function for a single Candidate on each entry of the given candidate_vector.
98102
* If OpenMP parallelization is activated (default) the execution of the run function for each member
99-
* of candidate_vector is parallelized. However, the secondaries are still processed in order.
103+
* of candidate_vector is parallelized.
100104
* @param candidates Candidate vector
101105
* @param recursive Whether to also process possible created secondaries
102106
* @param secondariesFirst Whether to process the secondaries directly after the
103107
* step where they are created or to only process them after the primary is fully finished
108+
* @param waitForSecondaries Whether to wait for the secondaries to be fully processed
109+
* before continuing with the primary candidate if secondariesFirst is set to true
104110
*/
105-
void run(const candidate_vector_t *candidates, bool recursive = true, bool secondariesFirst = true);
111+
void run(const candidate_vector_t *candidates, bool recursive = true, bool secondariesFirst = true, bool waitForSecondaries = true);
106112
/** Run function
107113
* This function generates count Candidates over the given source.
108114
* Each generated Candidate is then handed over to ModuleList::run(Candidate*)
109115
* where it is simulated.
110116
* If OpenMP parallelization is activated (default) the count primary Candidates are
111-
* generated and simulated in parallel. However, the secondaries are still processed in order.
117+
* generated and simulated in parallel.
112118
* @param source The source to generate Candidates from
113119
* @param count The number of Candidates to simulate
114120
* @param recursive Whether to also process possible created secondaries
115121
* @param secondariesFirst Whether to process the secondaries directly after the
116122
* step where they are created or to only process them after the primary is fully finished
123+
* @param waitForSecondaries Whether to wait for the secondaries to be fully processed
124+
* before continuing with the primary candidate if secondariesFirst is set to true
117125
*/
118-
void run(SourceInterface* source, size_t count, bool recursive = true, bool secondariesFirst = true);
126+
void run(SourceInterface* source, size_t count, bool recursive = true, bool secondariesFirst = true, bool waitForSecondaries = true);
119127

120128
/// @return Returns the description string for all modules
121129
std::string getDescription() const;

src/ModuleList.cpp.in

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -61,40 +61,54 @@ void ModuleList::process(ref_ptr<Candidate> candidate) const {
6161
process((Candidate*) candidate);
6262
}
6363

64-
void ModuleList::run(Candidate* candidate, bool recursive, bool secondariesFirst) {
64+
void ModuleList::run(Candidate* candidate, bool recursive, bool secondariesFirst, bool waitForSecondaries) {
65+
66+
int taskedSecondaries = 0; //Secondaries already submitted as tasks for all threads
67+
6568
// propagate primary candidate until finished
6669
while (candidate->isActive() && (g_cancel_signal_flag == 0)) {
6770
process(candidate);
6871

6972
// propagate all secondaries before next step of primary
7073
if (recursive and secondariesFirst) {
71-
for (size_t i = 0; i < candidate->secondaries.size(); i++) {
74+
#pragma omp taskloop num_tasks(2 * omp_get_max_threads()) untied
75+
for (size_t i = taskedSecondaries; i < candidate->secondaries.size(); i++) {
7276
if (g_cancel_signal_flag != 0)
73-
break;
77+
continue;
7478
run(candidate->secondaries[i], recursive, secondariesFirst);
7579
}
80+
81+
// increase counter of already tasked secondaries
82+
taskedSecondaries += candidate->secondaries.size();
83+
84+
// wait for completion of tasked secondaries or continue with primary
85+
if (waitForSecondaries) {
86+
#pragma omp taskwait
87+
}
7688
}
7789
}
7890

7991
// propagate secondaries after completing primary
8092
if (recursive and not secondariesFirst) {
81-
for (size_t i = 0; i < candidate->secondaries.size(); i++) {
93+
#pragma omp taskloop num_tasks(2 * omp_get_max_threads()) untied
94+
for (size_t i = taskedSecondaries; i < candidate->secondaries.size(); i++) {
8295
if (g_cancel_signal_flag != 0)
83-
break;
96+
continue;
8497
run(candidate->secondaries[i], recursive, secondariesFirst);
8598
}
99+
#pragma omp taskwait
86100
}
87101

88102
// dump candidae and secondaries if interrupted.
89103
if (candidate->isActive() && (g_cancel_signal_flag != 0))
90104
dumpCandidate(candidate);
91105
}
92106

93-
void ModuleList::run(ref_ptr<Candidate> candidate, bool recursive, bool secondariesFirst) {
94-
run((Candidate*) candidate, recursive, secondariesFirst);
107+
void ModuleList::run(ref_ptr<Candidate> candidate, bool recursive, bool secondariesFirst, bool waitForSecondaries) {
108+
run((Candidate*) candidate, recursive, secondariesFirst, waitForSecondaries);
95109
}
96110

97-
void ModuleList::run(const candidate_vector_t *candidates, bool recursive, bool secondariesFirst) {
111+
void ModuleList::run(const candidate_vector_t *candidates, bool recursive, bool secondariesFirst, bool waitForSecondaries) {
98112
size_t count = candidates->size();
99113

100114
#if _OPENMP
@@ -122,7 +136,7 @@ void ModuleList::run(const candidate_vector_t *candidates, bool recursive, bool
122136
}
123137

124138
try {
125-
run(candidates->operator[](i), recursive);
139+
run(candidates->operator[](i), recursive, secondariesFirst, waitForSecondaries);
126140
} catch (std::exception &e) {
127141
std::cerr << "Exception in crpropa::ModuleList::run: " << std::endl;
128142
std::cerr << e.what() << std::endl;
@@ -150,12 +164,11 @@ void ModuleList::run(const candidate_vector_t *candidates, bool recursive, bool
150164
}
151165
}
152166

153-
void ModuleList::run(SourceInterface *source, size_t count, bool recursive, bool secondariesFirst) {
167+
void ModuleList::run(SourceInterface *source, size_t count, bool recursive, bool secondariesFirst, bool waitForSecondaries) {
154168

155169
#if _OPENMP
156170
std::cout << "crpropa::ModuleList: Number of Threads: " << omp_get_max_threads() << std::endl;
157171
#endif
158-
159172
ProgressBar progressbar(count);
160173

161174
if (showProgress) {
@@ -189,7 +202,7 @@ void ModuleList::run(SourceInterface *source, size_t count, bool recursive, bool
189202

190203
if (candidate.valid()) {
191204
try {
192-
run(candidate, recursive);
205+
run(candidate, recursive, secondariesFirst, waitForSecondaries);
193206
} catch (std::exception &e) {
194207
std::cerr << "Exception in crpropa::ModuleList::run: " << std::endl;
195208
std::cerr << e.what() << std::endl;

0 commit comments

Comments
 (0)