@@ -55,6 +55,14 @@ namespace detail {
5555// / \f]
5656// / where the positive, real root of \f$P_{\rm{row}}\f$ give the optimal
5757// / optimal communication time.
58+
59+ // / Tag to disambiguate the rank-subset ProcGrid constructor from the
60+ // / (same-arity) test-only constructor.
61+ struct rank_subset_t {
62+ explicit rank_subset_t () = default;
63+ };
64+ inline constexpr rank_subset_t rank_subset{};
65+
5866class ProcGrid {
5967 public:
6068 typedef uint_fast32_t size_type;
@@ -71,9 +79,12 @@ class ProcGrid {
7179 // /< may be less than the number of processes in world.
7280 ProcessID rank_row_; // /< This process's row in the process grid
7381 ProcessID rank_col_; // /< This process's column in the process grid
74- size_type local_rows_; // /< The number of local element rows
75- size_type local_cols_; // /< The number of local element columns
76- size_type local_size_; // /< Number of local elements
82+ ProcessID rank_offset_ = 0 ; // /< World rank of the grid's first process
83+ // /< (nonzero for a grid over a contiguous
84+ // /< subset of the world's ranks)
85+ size_type local_rows_; // /< The number of local element rows
86+ size_type local_cols_; // /< The number of local element columns
87+ size_type local_size_; // /< Number of local elements
7788
7889 // / Compute the number of process rows that minimizes communication
7990
@@ -180,14 +191,16 @@ class ProcGrid {
180191 proc_cols_ = 1u ;
181192 proc_size_ = 1u ;
182193
183- // Set this process rank
184- rank_row_ = 0 ;
185- rank_col_ = 0 ;
194+ if (rank < proc_size_) {
195+ // Set this process rank
196+ rank_row_ = 0 ;
197+ rank_col_ = 0 ;
186198
187- // Set local counts
188- local_rows_ = rows_;
189- local_cols_ = cols_;
190- local_size_ = size_;
199+ // Set local counts
200+ local_rows_ = rows_;
201+ local_cols_ = cols_;
202+ local_size_ = size_;
203+ }
191204
192205 } else if (size_ <= nprocs) { // Max one tile per process
193206
@@ -291,6 +304,48 @@ class ProcGrid {
291304 init (world_->rank (), world_->size (), row_size, col_size);
292305 }
293306
307+ // / Construct a process grid over a contiguous subset of the world's ranks
308+
309+ // / The grid spans world ranks [rank_offset, rank_offset + nprocs); ranks
310+ // / outside that interval construct a valid "not in the grid" instance
311+ // / (zero local sizes, empty groups). Used by the h-grouped (3-d) batched
312+ // / Summa, where each fused-index slab group runs its own 2-d grid.
313+ // / \param world The world where the process grid will live
314+ // / \param rank_offset The world rank of the grid's first process
315+ // / \param nprocs The number of processes spanned by the grid
316+ // / \param rows The number of tile rows
317+ // / \param cols The number of tile columns
318+ // / \param row_size The number of element rows
319+ // / \param col_size The number of element columns
320+ ProcGrid (World& world, rank_subset_t , const ProcessID rank_offset,
321+ const size_type nprocs, const size_type rows, const size_type cols,
322+ const std::size_t row_size, const std::size_t col_size)
323+ : world_(&world),
324+ rows_(rows),
325+ cols_(cols),
326+ size_(rows_ * cols_),
327+ proc_rows_(0ul ),
328+ proc_cols_(0ul ),
329+ proc_size_(0ul ),
330+ rank_row_(-1 ),
331+ rank_col_(-1 ),
332+ rank_offset_(rank_offset),
333+ local_rows_(0ul ),
334+ local_cols_(0ul ),
335+ local_size_(0ul ) {
336+ TA_ASSERT (rank_offset >= 0 );
337+ TA_ASSERT (nprocs >= 1u );
338+ TA_ASSERT (rank_offset + nprocs <= size_type (world.size ()));
339+ const auto world_rank = world.rank ();
340+ // out-of-grid ranks pass rank == nprocs, which every init() branch
341+ // treats as "not in the grid"
342+ const size_type rank = (world_rank >= rank_offset &&
343+ world_rank < rank_offset + ProcessID (nprocs))
344+ ? world_rank - rank_offset
345+ : nprocs;
346+ init (rank, nprocs, row_size, col_size);
347+ }
348+
294349#ifdef TILEDARRAY_ENABLE_TEST_PROC_GRID
295350 // Note: The following function is here for testing purposes only. It
296351 // has the same functionality as the default constructor above, except the
@@ -350,6 +405,7 @@ class ProcGrid {
350405 proc_size_(other.proc_size_),
351406 rank_row_(other.rank_row_),
352407 rank_col_(other.rank_col_),
408+ rank_offset_(other.rank_offset_),
353409 local_rows_(other.local_rows_),
354410 local_cols_(other.local_cols_),
355411 local_size_(other.local_size_) {}
@@ -367,6 +423,7 @@ class ProcGrid {
367423 proc_size_ = other.proc_size_ ;
368424 rank_row_ = other.rank_row_ ;
369425 rank_col_ = other.rank_col_ ;
426+ rank_offset_ = other.rank_offset_ ;
370427 local_rows_ = other.local_rows_ ;
371428 local_cols_ = other.local_cols_ ;
372429 local_size_ = other.local_size_ ;
@@ -447,7 +504,7 @@ class ProcGrid {
447504 // Populate the row process list
448505 size_type p = rank_row_ * proc_cols_;
449506 const size_type row_end = p + proc_cols_;
450- for (; p < row_end; ++p) proc_list.push_back (p);
507+ for (; p < row_end; ++p) proc_list.push_back (p + rank_offset_ );
451508
452509 // Construct the group
453510 group = madness::Group (*world_, proc_list, did);
@@ -472,7 +529,7 @@ class ProcGrid {
472529
473530 // Populate the column process list
474531 for (size_type p = rank_col_; p < proc_size_; p += proc_cols_)
475- proc_list.push_back (p);
532+ proc_list.push_back (p + rank_offset_ );
476533
477534 // Construct the group
478535 if (proc_list.size () != 0 )
@@ -489,7 +546,7 @@ class ProcGrid {
489546 // / (row,rank_col)
490547 ProcessID map_row (const size_type row) const {
491548 TA_ASSERT (row < proc_rows_);
492- return rank_col_ + row * proc_cols_;
549+ return rank_col_ + row * proc_cols_ + rank_offset_ ;
493550 }
494551
495552 // / Map a column to the process in this process's row
@@ -499,7 +556,7 @@ class ProcGrid {
499556 // / (rank_row,col)
500557 ProcessID map_col (const size_type col) const {
501558 TA_ASSERT (col < proc_cols_);
502- return rank_row_ * proc_cols_ + col;
559+ return rank_row_ * proc_cols_ + col + rank_offset_ ;
503560 }
504561
505562 // / Construct a cyclic process
0 commit comments