BioCMAMC-ST
contribution_kernel.hpp
1#ifndef __CONTRIBUTION_KERNEL_HPP__
2#define __CONTRIBUTION_KERNEL_HPP__
3#include "Kokkos_Assert.hpp"
4#include "Kokkos_Macros.hpp"
5#include "mc/events.hpp"
6#include <Kokkos_Core.hpp>
7#include <mc/particles_container.hpp>
8#include <mc/traits.hpp>
9#include <simulation/kernels/cycle_reducer.hpp>
10#include <simulation/probe.hpp>
11template <ModelType M> struct ContributionFunctor
12{
13
14 struct Tag0D
15 {
16 };
17 struct Tag3D
18 {
19 };
20
21 using TeamPolicy = Kokkos::TeamPolicy<ComputeSpace>;
22 using TeamMember = TeamPolicy::member_type;
23 using float_type = float;
25 = Kokkos::View<float_type*,
26 TeamPolicy::execution_space::scratch_memory_space>;
30 std::size_t m_particle_per_team;
37 M::FloatType d_t;
41 ContributionFunctor(std::size_t particle_per_team,
42 MC::ContributionView contribution_scatter,
45 MC::KernelConcentrationType _concentrations,
46 MC::EventContainer _event,
48 : m_particle_per_team(particle_per_team),
49 m_contribution_scatter(std::move(contribution_scatter)),
50 m_particles(std::move(particles)), random_pool(rp),
51 concentrations(std::move(_concentrations)), events(std::move(_event)),
52 division_probe(std::move(d_probes))
53 {
54 }
56 size_t np{};
57
58 void
59 update(MC::ParticlesContainer<M> _particles, double _d_t)
60
61 {
62 this->d_t = _d_t;
63 this->m_particles = std::move(_particles);
64 np = m_particles.n_particles();
65 }
66
67 KOKKOS_INLINE_FUNCTION void
68 division(const std::size_t idx, value_type& local_reduce) const
69 {
70
71 using mem_space = ComputeSpace::memory_space;
72 if constexpr (AutoGenerated::FlagCompileTime::use_probe)
73 {
74 // Register probe here to sample BEFORE division and even if
75 // division procedure fails to spawn new particle, the age is
76 // still the same
77 const auto _ = this->division_probe.template set<mem_space>(
78 m_particles.ages(idx, 1)); // Skip error
79 }
80
81 if (!m_particles.handle_division(random_pool, idx)) [[unlikely]]
82 {
83 local_reduce.waiting_allocation_particle += 1;
85 Kokkos::printf("[KERNEL] Division Overflow\r\n");
86 }
87
89 }
90
91 KOKKOS_INLINE_FUNCTION
92 void
93 operator()(Tag0D _tag,
94 const TeamMember& team,
95 value_type& team_value_reduce) const
96 {
97 (void)_tag;
98 static const auto n_c = M::n_c;
99 const std::size_t p0 = team.league_rank() * m_particle_per_team;
100 const std::size_t n_particle = m_particles.n_particles();
101 const auto& status = m_particles.status;
102 const auto& contribs = m_particles.contribs;
103 const auto& cs = m_contribution_scatter;
104
105 ScratchView scratch(team.team_scratch(0), n_c);
106
107 Kokkos::parallel_for(Kokkos::TeamVectorRange(team, n_c),
108 [&](const std::size_t j)
109 { scratch(j) = float_type{ 0 }; });
110
111 const auto upper_bound = ((p0 + m_particle_per_team) >= n_particle)
112 ? n_particle - p0
114
115 KOKKOS_ASSERT(upper_bound > 0 && upper_bound <= m_particle_per_team
116 && (p0 + upper_bound) <= n_particle);
117
118 value_type value_reduce;
119
120 Kokkos::parallel_reduce(
121 Kokkos::TeamThreadRange(team, 0, upper_bound),
122 [&](std::size_t relative_index, value_type& local_value_reduce)
123 {
124 const std::size_t flatten_index = p0 + relative_index;
125 KOKKOS_ASSERT(flatten_index < n_particle);
126 const bool active = status(flatten_index) == MC::Status::Idle;
127
128 if (active)
129 {
130 // const auto pos = m_particles.position(flatten_index);
131 // TODO: position array is useless in 0d, do not resize position
132 // array in 0D could be interessting
133 const auto pos = 0; // Position is always 0 in 0D
134 const auto weight = m_particles.get_weight(flatten_index);
135 const auto new_status = M::update(random_pool,
136 d_t,
137 flatten_index,
138 m_particles.model,
139 contribs,
140 pos,
142
143 for (std::size_t j = 0; j < n_c; ++j)
144 {
145 Kokkos::atomic_add(&scratch(j),
146 weight * contribs(flatten_index, j));
147 }
148
149 if (new_status == MC::Status::Division)
150 {
151 division(flatten_index, local_value_reduce);
152 }
153 else
154 {
155 m_particles.ages(flatten_index, 1) += d_t;
156 }
157 }
158 },
159 value_reduce);
160
161 team.team_barrier();
162
163 Kokkos::single(Kokkos::PerTeam(team),
164 [&]()
165 {
166 auto access = cs.access();
167 team_value_reduce += value_reduce;
168 for (std::size_t j = 0; j < M::n_c; ++j)
169 {
170 access(j, 0) += scratch(j);
171 }
172 });
173 }
174
175 KOKKOS_INLINE_FUNCTION
176 void
177 operator()(const Tag3D _tag,
178 const TeamMember& team,
179 value_type& team_value_reduce) const
180 {
181 (void)_tag;
182
183 const std::size_t N = m_particle_per_team;
184 const std::size_t p0 = team.league_rank() * N;
185 const auto _ntot = m_particles.n_particles();
186 const std::size_t p = team.team_size();
187
188 KOKKOS_ASSERT(p0 < _ntot)
189
190 const auto upper_bound = ((p0 + N) >= _ntot) ? _ntot - p0 : N;
191
192 KOKKOS_ASSERT(upper_bound > 0 && upper_bound <= _ntot);
193
194 const std::size_t m = (upper_bound + p - 1) / p;
195
196 const auto& positions = m_particles.position;
197 const auto& contribs = m_particles.contribs;
198 const auto& status = m_particles.status;
199
200 value_type value_reduce;
201
202 Kokkos::parallel_reduce(
203 Kokkos::TeamThreadRange(team, 0, upper_bound),
204 [&](const std::size_t i, value_type& local_value_reduce)
205 {
206 const std::size_t flatten_index = p0 + i;
207 KOKKOS_ASSERT(flatten_index < _ntot);
208 const bool active = status(flatten_index) == MC::Status::Idle;
209 if (active)
210 {
211 const auto pos = m_particles.position(flatten_index);
212 const auto weight = m_particles.get_weight(flatten_index);
213 const auto new_status = M::update(random_pool,
214 d_t,
215 flatten_index,
216 m_particles.model,
217 contribs,
218 pos,
220
221 if (new_status == MC::Status::Division)
222 {
223 division(flatten_index, local_value_reduce);
224 }
225 else
226 {
227 m_particles.ages(flatten_index, 1) += d_t;
228 }
229 }
230 },
231 value_reduce);
232
233 team.team_barrier();
234
235 Kokkos::single(Kokkos::PerTeam(team),
236 [&]() { team_value_reduce += value_reduce; });
237
238 Kokkos::parallel_for(
239 Kokkos::TeamThreadRange(team, 0, p),
240 [&](const std::size_t tid)
241 {
242 auto access = m_contribution_scatter.access();
243 for (std::size_t k = 0; k < m; ++k)
244 {
245 const std::size_t base = tid + k * p; // stride p
246 const std::size_t flat_index = p0 + base;
247 if (base >= upper_bound)
248 {
249 break;
250 }
251 if (status(flat_index) != MC::Status::Idle)
252 {
253 continue;
254 }
255
256 KOKKOS_ASSERT(flat_index < _ntot);
257
258 const double weight = m_particles.get_weight(flat_index);
259 const auto pos = positions(flat_index);
260 Kokkos::parallel_for(
261 Kokkos::ThreadVectorRange(team, 0, M::n_c),
262 [&](const int j)
263 { access(j, pos) += weight * contribs(flat_index, j); });
264 }
265 });
266 }
267};
268
269#endif
Main owning object for Monte-Carlo particles.
Definition particles_container.hpp:59
@ Overflow
Definition events.hpp:25
@ NewParticle
Spawn new particle.
Definition events.hpp:21
decltype(Kokkos::Experimental::create_scatter_view( kernelContribution())) ContributionView
Definition alias.hpp:162
@ Division
Definition alias.hpp:127
@ Idle
Definition alias.hpp:126
gen_pool_type< Kokkos::DefaultExecutionSpace > pool_type
Definition alias.hpp:100
Kokkos::View< const double **, Kokkos::LayoutLeft, ComputeSpace, Kokkos::MemoryTraits< Kokkos::RandomAccess > > KernelConcentrationType
Definition alias.hpp:165
Probes< AutoGenerated::probe_buffer_size > ProbeAutogeneratedBuffer
Definition probe.hpp:150
Definition contribution_kernel.hpp:15
Definition contribution_kernel.hpp:18
Kokkos::View< float_type *, TeamPolicy::execution_space::scratch_memory_space > ScratchView
Definition contribution_kernel.hpp:24
TeamPolicy::member_type TeamMember
Definition contribution_kernel.hpp:22
M::FloatType d_t
Definition contribution_kernel.hpp:36
KOKKOS_INLINE_FUNCTION void operator()(Tag0D _tag, const TeamMember &team, value_type &team_value_reduce) const
Definition contribution_kernel.hpp:92
KOKKOS_INLINE_FUNCTION void division(const std::size_t idx, value_type &local_reduce) const
Definition contribution_kernel.hpp:67
ContributionFunctor(std::size_t particle_per_team, MC::ContributionView contribution_scatter, MC::ParticlesContainer< M > particles, MC::pool_type rp, MC::KernelConcentrationType _concentrations, MC::EventContainer _event, Simulation::ProbeAutogeneratedBuffer d_probes)
Definition contribution_kernel.hpp:40
Simulation::ProbeAutogeneratedBuffer division_probe
Definition contribution_kernel.hpp:38
MC::ParticlesContainer< M > m_particles
Definition contribution_kernel.hpp:32
Kokkos::TeamPolicy< ComputeSpace > TeamPolicy
Definition contribution_kernel.hpp:21
MC::EventContainer events
Definition contribution_kernel.hpp:37
MC::pool_type random_pool
Definition contribution_kernel.hpp:34
size_t np
Definition contribution_kernel.hpp:55
Simulation::KernelInline::CycleReducerType value_type
Definition contribution_kernel.hpp:27
float float_type
Definition contribution_kernel.hpp:23
MC::KernelConcentrationType concentrations
Definition contribution_kernel.hpp:35
MC::ContributionView m_contribution_scatter
Definition contribution_kernel.hpp:31
void update(MC::ParticlesContainer< M > _particles, double _d_t)
Definition contribution_kernel.hpp:58
std::size_t m_particle_per_team
Definition contribution_kernel.hpp:29
Use to count events that occurs during Monte-Carlo processing cycles.
Definition events.hpp:168
Definition cycle_reducer.hpp:15
std::size_t waiting_allocation_particle
Definition cycle_reducer.hpp:16