Cabana 0.8.0-dev
 
Loading...
Searching...
No Matches
Cabana_Grid_Parallel.hpp
Go to the documentation of this file.
1/****************************************************************************
2 * Copyright (c) 2018-2023 by the Cabana authors *
3 * All rights reserved. *
4 * *
5 * This file is part of the Cabana library. Cabana is distributed under a *
6 * BSD 3-clause license. For the licensing terms see the LICENSE file in *
7 * the top-level directory. *
8 * *
9 * SPDX-License-Identifier: BSD-3-Clause *
10 ****************************************************************************/
11
16#ifndef CABANA_GRID_PARALLEL_HPP
17#define CABANA_GRID_PARALLEL_HPP
18
21
22#include <Kokkos_Profiling_ScopedRegion.hpp>
23
24#include <string>
25
26namespace Cabana
27{
28namespace Grid
29{
30//---------------------------------------------------------------------------//
31// Grid Parallel For
32//---------------------------------------------------------------------------//
51template <class FunctorType, class ExecutionSpace, long N>
52inline void grid_parallel_for( const std::string& label,
53 const ExecutionSpace& exec_space,
54 const IndexSpace<N>& index_space,
55 const FunctorType& functor )
56{
57 Kokkos::Profiling::ScopedRegion region( "Cabana::Grid::grid_parallel_for" );
58 Kokkos::parallel_for(
59 label, createExecutionPolicy( index_space, exec_space ), functor );
60}
61
62//---------------------------------------------------------------------------//
85template <class FunctorType, class WorkTag, class ExecutionSpace, long N>
86inline void
87grid_parallel_for( const std::string& label, const ExecutionSpace& exec_space,
88 const IndexSpace<N>& index_space, const WorkTag& work_tag,
89 const FunctorType& functor )
90{
91 Kokkos::Profiling::ScopedRegion region( "Cabana::Grid::grid_parallel_for" );
92 Kokkos::parallel_for(
93 label, createExecutionPolicy( index_space, exec_space, work_tag ),
94 functor );
95}
96
97//---------------------------------------------------------------------------//
121template <class FunctorType, class ExecutionSpace, class MeshType,
122 class DecompositionType, class EntityType>
123inline void
124grid_parallel_for( const std::string& label, const ExecutionSpace& exec_space,
125 const LocalGrid<MeshType>& local_grid,
126 const DecompositionType& decomposition,
127 const EntityType& entity_type, const FunctorType& functor )
128{
129 auto index_space =
130 local_grid.indexSpace( decomposition, entity_type, Local() );
131 grid_parallel_for( label, exec_space, index_space, functor );
132}
133
134//---------------------------------------------------------------------------//
162template <class FunctorType, class WorkTag, class ExecutionSpace,
163 class MeshType, class DecompositionType, class EntityType>
164inline void
165grid_parallel_for( const std::string& label, const ExecutionSpace& exec_space,
166 const LocalGrid<MeshType>& local_grid,
167 const DecompositionType& decomposition,
168 const EntityType& entity_type, const WorkTag& work_tag,
169 const FunctorType& functor )
170{
171 auto index_space =
172 local_grid.indexSpace( decomposition, entity_type, Local() );
173 grid_parallel_for( label, exec_space, index_space, work_tag, functor );
174}
175
176//---------------------------------------------------------------------------//
196template <class FunctorType, class ExecutionSpace, std::size_t NumSpace>
197inline void
198grid_parallel_for( const std::string& label, const ExecutionSpace& exec_space,
199 const Kokkos::Array<IndexSpace<4>, NumSpace>& index_spaces,
200 const FunctorType& functor )
201{
202 Kokkos::Profiling::ScopedRegion region( "Cabana::Grid::grid_parallel_for" );
203
204 // Compute the total number of threads needed and the index space offsets
205 // via inclusive scan.
206 int size = index_spaces[0].size();
207 Kokkos::Array<int, NumSpace> exclusive_offsets;
208 Kokkos::Array<int, NumSpace> inclusive_offsets;
209 exclusive_offsets[0] = 0;
210 inclusive_offsets[0] = size;
211 for ( std::size_t sp = 1; sp < NumSpace; ++sp )
212 {
213 size += index_spaces[sp].size();
214 exclusive_offsets[sp] =
215 exclusive_offsets[sp - 1] + index_spaces[sp - 1].size();
216 inclusive_offsets[sp] =
217 inclusive_offsets[sp - 1] + index_spaces[sp].size();
218 }
219
220 // Unroll the index spaces into a linear parallel for.
221 Kokkos::parallel_for(
222 label, Kokkos::RangePolicy<ExecutionSpace>( exec_space, 0, size ),
223 KOKKOS_LAMBDA( const int n ) {
224 // Get the index space id.
225 int s = -1;
226 for ( std::size_t sp = 0; sp < NumSpace; ++sp )
227 {
228 if ( n < inclusive_offsets[sp] )
229 {
230 s = sp;
231 break;
232 }
233 }
234
235 // Linear id in index space.
236 int linear_id = n - exclusive_offsets[s];
237
238 // Compute entity id.
239 int extent_l = index_spaces[s].extent( 3 );
240 int extent_kl = extent_l * index_spaces[s].extent( Dim::K );
241 int extent_jkl = extent_kl * index_spaces[s].extent( Dim::J );
242 int i_base = linear_id / extent_jkl;
243 int stride_j = extent_jkl * i_base;
244 int j_base = ( linear_id - stride_j ) / extent_kl;
245 int stride_k = ( stride_j + extent_kl * j_base );
246 int k_base = ( linear_id - stride_k ) / extent_l;
247 int l_base = linear_id - stride_k - k_base * extent_l;
248
249 // Execute the user functor. Provide the index space id so they
250 // can discern which space they are in within the functor.
251 functor( s, i_base + index_spaces[s].min( Dim::I ),
252 j_base + index_spaces[s].min( Dim::J ),
253 k_base + index_spaces[s].min( Dim::K ),
254 l_base + index_spaces[s].min( 3 ) );
255 } );
256}
257
258//---------------------------------------------------------------------------//
278template <class FunctorType, class ExecutionSpace, std::size_t NumSpace>
279inline void
280grid_parallel_for( const std::string& label, const ExecutionSpace& exec_space,
281 const Kokkos::Array<IndexSpace<3>, NumSpace>& index_spaces,
282 const FunctorType& functor )
283{
284 Kokkos::Profiling::ScopedRegion region( "Cabana::Grid::grid_parallel_for" );
285
286 // Compute the total number of threads needed and the index space offsets
287 // via inclusive scan.
288 int size = index_spaces[0].size();
289 Kokkos::Array<int, NumSpace> exclusive_offsets;
290 Kokkos::Array<int, NumSpace> inclusive_offsets;
291 exclusive_offsets[0] = 0;
292 inclusive_offsets[0] = size;
293 for ( std::size_t sp = 1; sp < NumSpace; ++sp )
294 {
295 size += index_spaces[sp].size();
296 exclusive_offsets[sp] =
297 exclusive_offsets[sp - 1] + index_spaces[sp - 1].size();
298 inclusive_offsets[sp] =
299 inclusive_offsets[sp - 1] + index_spaces[sp].size();
300 }
301
302 // Unroll the index spaces into a linear parallel for.
303 Kokkos::parallel_for(
304 label, Kokkos::RangePolicy<ExecutionSpace>( exec_space, 0, size ),
305 KOKKOS_LAMBDA( const int n ) {
306 // Get the index space id.
307 int s = -1;
308 for ( std::size_t sp = 0; sp < NumSpace; ++sp )
309 {
310 if ( n < inclusive_offsets[sp] )
311 {
312 s = sp;
313 break;
314 }
315 }
316
317 // Linear id in index space.
318 int linear_id = n - exclusive_offsets[s];
319
320 // Compute entity id.
321 int extent_k = index_spaces[s].extent( Dim::K );
322 int extent_jk = extent_k * index_spaces[s].extent( Dim::J );
323 int i_base = linear_id / extent_jk;
324 int stride_j = extent_jk * i_base;
325 int j_base = ( linear_id - stride_j ) / extent_k;
326 int k_base = linear_id - extent_k * j_base - stride_j;
327
328 // Execute the user functor. Provide the index space id so they
329 // can discern which space they are in within the functor.
330 functor( s, i_base + index_spaces[s].min( Dim::I ),
331 j_base + index_spaces[s].min( Dim::J ),
332 k_base + index_spaces[s].min( Dim::K ) );
333 } );
334}
335
336//---------------------------------------------------------------------------//
356template <class FunctorType, class ExecutionSpace, std::size_t NumSpace>
357inline void
358grid_parallel_for( const std::string& label, const ExecutionSpace& exec_space,
359 const Kokkos::Array<IndexSpace<2>, NumSpace>& index_spaces,
360 const FunctorType& functor )
361{
362 Kokkos::Profiling::ScopedRegion region( "Cabana::Grid::grid_parallel_for" );
363
364 // Compute the total number of threads needed and the index space offsets
365 // via inclusive scan.
366 int size = index_spaces[0].size();
367 Kokkos::Array<int, NumSpace> exclusive_offsets;
368 Kokkos::Array<int, NumSpace> inclusive_offsets;
369 exclusive_offsets[0] = 0;
370 inclusive_offsets[0] = size;
371 for ( std::size_t sp = 1; sp < NumSpace; ++sp )
372 {
373 size += index_spaces[sp].size();
374 exclusive_offsets[sp] =
375 exclusive_offsets[sp - 1] + index_spaces[sp - 1].size();
376 inclusive_offsets[sp] =
377 inclusive_offsets[sp - 1] + index_spaces[sp].size();
378 }
379
380 // Unroll the index spaces into a linear parallel for.
381 Kokkos::parallel_for(
382 label, Kokkos::RangePolicy<ExecutionSpace>( exec_space, 0, size ),
383 KOKKOS_LAMBDA( const int n ) {
384 // Get the index space id.
385 int s = -1;
386 for ( std::size_t sp = 0; sp < NumSpace; ++sp )
387 {
388 if ( n < inclusive_offsets[sp] )
389 {
390 s = sp;
391 break;
392 }
393 }
394
395 // Linear id in index space.
396 int linear_id = n - exclusive_offsets[s];
397
398 // Compute entity id.
399 int extent_j = index_spaces[s].extent( Dim::J );
400 int i_base = linear_id / extent_j;
401 int j_base = linear_id - i_base * extent_j;
402
403 // Execute the user functor. Provide the index space id so they
404 // can discern which space they are in within the functor.
405 functor( s, i_base + index_spaces[s].min( Dim::I ),
406 j_base + index_spaces[s].min( Dim::J ) );
407 } );
408}
409
410//---------------------------------------------------------------------------//
411// Grid Parallel Reduce
412//---------------------------------------------------------------------------//
435template <class FunctorType, class ExecutionSpace, long N, class ReduceType>
436inline void grid_parallel_reduce( const std::string& label,
437 const ExecutionSpace& exec_space,
438 const IndexSpace<N>& index_space,
439 const FunctorType& functor,
440 ReduceType& reducer )
441{
442 Kokkos::Profiling::ScopedRegion region(
443 "Cabana::Grid::grid_parallel_reduce" );
444 Kokkos::parallel_reduce( label,
445 createExecutionPolicy( index_space, exec_space ),
446 functor, reducer );
447}
448
449//---------------------------------------------------------------------------//
476template <class FunctorType, class WorkTag, class ExecutionSpace, long N,
477 class ReduceType>
478inline void
479grid_parallel_reduce( const std::string& label,
480 const ExecutionSpace& exec_space,
481 const IndexSpace<N>& index_space, const WorkTag& work_tag,
482 const FunctorType& functor, ReduceType& reducer )
483{
484 Kokkos::Profiling::ScopedRegion region(
485 "Cabana::Grid::grid_parallel_reduce" );
486 Kokkos::parallel_reduce(
487 label, createExecutionPolicy( index_space, exec_space, work_tag ),
488 functor, reducer );
489}
490
491//---------------------------------------------------------------------------//
519template <class FunctorType, class ExecutionSpace, class MeshType,
520 class DecompositionType, class EntityType, class ReduceType>
521inline void grid_parallel_reduce( const std::string& label,
522 const ExecutionSpace& exec_space,
523 const LocalGrid<MeshType>& local_grid,
524 const DecompositionType& decomposition,
525 const EntityType& entity_type,
526 const FunctorType& functor,
527 ReduceType& reducer )
528{
529 auto index_space =
530 local_grid.indexSpace( decomposition, entity_type, Local() );
531 grid_parallel_reduce( label, exec_space, index_space, functor, reducer );
532}
533
534//---------------------------------------------------------------------------//
566template <class FunctorType, class WorkTag, class ExecutionSpace,
567 class MeshType, class DecompositionType, class EntityType,
568 class ReduceType>
570 const std::string& label, const ExecutionSpace& exec_space,
571 const LocalGrid<MeshType>& local_grid,
572 const DecompositionType& decomposition, const EntityType& entity_type,
573 const WorkTag& work_tag, const FunctorType& functor, ReduceType& reducer )
574{
575 auto index_space =
576 local_grid.indexSpace( decomposition, entity_type, Local() );
577 grid_parallel_reduce( label, exec_space, index_space, work_tag, functor,
578 reducer );
579}
580
581//---------------------------------------------------------------------------//
582
583} // namespace Grid
584} // namespace Cabana
585
586#endif // end CABANA_GRID_PARALLEL_HPP
Logical grid indexing.
Kokkos::RangePolicy< ExecutionSpace > createExecutionPolicy(const IndexSpace< 1 > &index_space, const ExecutionSpace &)
Create a multi-dimensional execution policy over an index space.
Definition Cabana_Grid_IndexSpace.hpp:175
void grid_parallel_for(const std::string &label, const ExecutionSpace &exec_space, const IndexSpace< N > &index_space, const FunctorType &functor)
Execute a functor in parallel with a multidimensional execution policy specified by the given index s...
Definition Cabana_Grid_Parallel.hpp:52
void grid_parallel_reduce(const std::string &label, const ExecutionSpace &exec_space, const IndexSpace< N > &index_space, const FunctorType &functor, ReduceType &reducer)
Execute a reduction functor in parallel with a multidimensional execution policy specified by the giv...
Definition Cabana_Grid_Parallel.hpp:436
Structured index space.
Definition Cabana_Grid_IndexSpace.hpp:37
Local logical grid.
Definition Cabana_Grid_LocalGrid.hpp:39
IndexSpace< num_space_dim > indexSpace(DecompositionTag t1, EntityType t2, IndexType t3) const
Given a decomposition type, entity type, and index type, get the contiguous set of indices that span ...
Core: particle data structures and algorithms.
Definition Cabana_AoSoA.hpp:36
auto size(SliceType slice, typename std::enable_if< is_slice< SliceType >::value, int >::type *=0)
Check slice size (differs from Kokkos View).
Definition Cabana_Slice.hpp:1012
Local index tag.
Definition Cabana_Grid_Types.hpp:208