LCOV - code coverage report
Current view: top level - test - BlockPatternTest.cc (source / functions) Hit Total Coverage
Test: coverage.info.cleaned Lines: 519 582 89.2 %
Date: 2016-06-29 12:30:40 Functions: 60 60 100.0 %

          Line data    Source code
       1             : #include <libdash.h>
       2             : #include <gtest/gtest.h>
       3             : 
       4             : #include "TestBase.h"
       5             : #include "TestLogHelpers.h"
       6             : #include "BlockPatternTest.h"
       7             : 
       8          20 : TEST_F(BlockPatternTest, SimpleConstructor)
       9             : {
      10           4 :   DASH_TEST_LOCAL_ONLY();
      11           1 :   int extent_x = 21;
      12           1 :   int extent_y = 37;
      13           1 :   int extent_z = 41;
      14           1 :   int size = extent_x * extent_y * extent_z;
      15             :   // Should default to distribution BLOCKED, NONE, NONE:
      16           1 :   dash::Pattern<3> pat_default(extent_x, extent_y, extent_z);
      17           1 :   EXPECT_EQ(dash::DistributionSpec<3>(), pat_default.distspec());
      18           1 :   EXPECT_EQ(dash::Team::All(), pat_default.team());
      19           1 :   EXPECT_EQ(dash::Team::All().size(), pat_default.num_units());
      20           1 :   EXPECT_EQ(size, pat_default.capacity());
      21             : 
      22             :   dash::DistributionSpec<3> ds_blocked_z(
      23           1 :       dash::NONE, dash::NONE, dash::BLOCKED);
      24             :   dash::Pattern<3, dash::COL_MAJOR> pat_ds(
      25             :       extent_x, extent_y, extent_z,
      26           1 :       ds_blocked_z);
      27           1 :   EXPECT_EQ(ds_blocked_z, pat_ds.distspec());
      28           1 :   EXPECT_EQ(size, pat_ds.capacity());
      29             : 
      30             :   // Splits in consecutive test cases within a single test
      31             :   // run are not supported for now:
      32             :   // dash::Team & team_split_2 = dash::Team::All().split(2);
      33             :   dash::Pattern<3> pat_ds_t(
      34             :       extent_x, extent_y, extent_z,
      35             :       ds_blocked_z,
      36           1 :       dash::Team::All());
      37           1 :   EXPECT_EQ(ds_blocked_z, pat_ds_t.distspec());
      38           1 :   EXPECT_EQ(size, pat_ds_t.capacity());
      39           1 :   EXPECT_EQ(dash::Team::All().size(), pat_ds_t.num_units());
      40             : }
      41             : 
      42          20 : TEST_F(BlockPatternTest, EqualityComparison)
      43             : {
      44           4 :   DASH_TEST_LOCAL_ONLY();
      45           1 :   int num_units = dash::Team::All().size();
      46           1 :   int extent_x = 21;
      47           1 :   int extent_y = 37;
      48           1 :   int extent_z = 41;
      49           1 :   dash::Pattern<3> pat_1(extent_x, extent_y, extent_z);
      50           1 :   dash::Pattern<3> pat_2(extent_x, extent_y + 1, extent_z);
      51           1 :   dash::Pattern<3> pat_3(extent_x, extent_y + 1, extent_z,
      52           1 :                          dash::NONE, dash::BLOCKED, dash::NONE);
      53           1 :   dash::Pattern<3> pat_4(extent_x, extent_y + 1, extent_z,
      54           2 :                          dash::TeamSpec<3>(1,num_units,1));
      55             :   dash::Pattern<3> pat_5(extent_x, extent_y, extent_z,
      56           1 :                          dash::TeamSpec<3>(num_units,1,1));
      57           1 :   EXPECT_EQ(pat_1, pat_1);
      58           1 :   EXPECT_EQ(pat_1, pat_5);
      59           1 :   EXPECT_NE(pat_1, pat_2);
      60           1 :   EXPECT_NE(pat_1, pat_3);
      61           1 :   EXPECT_NE(pat_1, pat_4);
      62             : }
      63             : 
      64          20 : TEST_F(BlockPatternTest, CopyConstructorAndAssignment)
      65             : {
      66           4 :   DASH_TEST_LOCAL_ONLY();
      67           1 :   int extent_x = 12;
      68           1 :   int extent_y = 13;
      69           1 :   int extent_z = 14;
      70             :   // Splits in consecutive test cases within a single test
      71             :   // run are not supported for now:
      72             :   // dash::Team & team_split_2 = dash::Team::All().split(2);
      73           1 :   int num_units = dash::Team::All().size();
      74           1 :   if (num_units % 2 == 0) {
      75             :     // This test requires that (2 * 1 * (num_units/2)) == num_units
      76           1 :     dash::TeamSpec<3> teamspec_2_by_n(2, 1, num_units / 2);
      77             :     dash::Pattern<3> pat_org(
      78             :         dash::SizeSpec<3>(3, 7, 13),
      79             :         dash::DistributionSpec<3>(dash::BLOCKED, dash::NONE, dash::CYCLIC),
      80             :         teamspec_2_by_n,
      81           1 :         dash::Team::All());
      82             : 
      83           1 :     dash::Pattern<3> pat_copy(pat_org);
      84           1 :     dash::Pattern<3> pat_assign(extent_x, extent_y, extent_z);
      85           1 :     pat_assign = pat_org;
      86             :   }
      87             : }
      88             : 
      89          20 : TEST_F(BlockPatternTest, Distribute1DimBlocked)
      90             : {
      91           4 :   DASH_TEST_LOCAL_ONLY();
      92             :   typedef dash::default_index_t index_t;
      93             : 
      94             :   // Simple 1-dimensional blocked partitioning:
      95             :   //
      96             :   // [ .. team 0 .. | .. team 1 .. | ... | team n-1 ]
      97           1 :   size_t team_size  = dash::Team::All().size();
      98             :   LOG_MESSAGE("Team size: %lu", team_size);
      99             :   // One underfilled block:
     100           1 :   _num_elem = 11 * team_size - 1;
     101           1 :   size_t block_size = dash::math::div_ceil(_num_elem, team_size);
     102           1 :   size_t local_cap  = block_size;
     103             :   dash::Pattern<1, dash::ROW_MAJOR> pat_blocked_row(
     104           1 :       dash::SizeSpec<1>(_num_elem),
     105             :       dash::DistributionSpec<1>(dash::BLOCKED),
     106             :       dash::TeamSpec<1>(),
     107           3 :       dash::Team::All());
     108             :   dash::Pattern<1, dash::COL_MAJOR> pat_blocked_col(
     109           1 :       dash::SizeSpec<1>(_num_elem),
     110             :       dash::DistributionSpec<1>(dash::BLOCKED),
     111             :       dash::TeamSpec<1>(),
     112           3 :       dash::Team::All());
     113           1 :   EXPECT_EQ(pat_blocked_row.capacity(), _num_elem);
     114           1 :   EXPECT_EQ(pat_blocked_row.blocksize(0), block_size);
     115           1 :   EXPECT_EQ(pat_blocked_row.local_capacity(), local_cap);
     116           1 :   EXPECT_EQ(pat_blocked_col.capacity(), _num_elem);
     117           1 :   EXPECT_EQ(pat_blocked_col.blocksize(0), block_size);
     118           1 :   EXPECT_EQ(pat_blocked_col.local_capacity(), local_cap);
     119             :   // Test local extents:
     120           5 :   for (size_t u = 0; u < team_size; ++u) {
     121             :     size_t local_extent_x;
     122           4 :     if (u < _num_elem / block_size) {
     123             :       // Full block
     124           3 :       local_extent_x = block_size;
     125           1 :     } else if (u == _num_elem / block_size) {
     126             :       // Underfilled block
     127           1 :       local_extent_x = _num_elem % block_size;
     128             :     } else {
     129             :       // Empty block
     130           0 :       local_extent_x = 0;
     131             :     }
     132             :     LOG_MESSAGE("local extents: u:%lu, le:%lu",
     133             :       u, local_extent_x);
     134           4 :     EXPECT_EQ(local_extent_x, pat_blocked_row.local_extents(u)[0]);
     135           4 :     EXPECT_EQ(local_extent_x, pat_blocked_col.local_extents(u)[0]);
     136             :   }
     137             :   std::array<index_t, 1> expected_coords;
     138          44 :   for (int x = 0; x < _num_elem; ++x) {
     139          43 :     int expected_unit_id = x / block_size;
     140          43 :     int expected_offset  = x % block_size;
     141          43 :     int expected_index   = x;
     142          43 :     expected_coords[0]   = x;
     143             :     LOG_MESSAGE("x: %d, eu: %d, eo: %d",
     144             :       x, expected_unit_id, expected_offset);
     145             :     // Row major:
     146          43 :     EXPECT_EQ(
     147             :       expected_coords,
     148           0 :       pat_blocked_row.coords(x));
     149          43 :     EXPECT_EQ(
     150             :       expected_unit_id,
     151           0 :       pat_blocked_row.unit_at(std::array<index_t, 1> { x }));
     152          43 :     EXPECT_EQ(
     153             :       expected_offset,
     154           0 :       pat_blocked_row.at(std::array<index_t, 1> { x }));
     155             :     auto glob_coords_row =
     156             :       pat_blocked_row.global(
     157          43 :         expected_unit_id, std::array<index_t, 1> { expected_offset });
     158          43 :     EXPECT_EQ(
     159             :       (std::array<index_t, 1> { expected_index }),
     160           0 :       glob_coords_row);
     161             :     // Column major:
     162          43 :     EXPECT_EQ(
     163             :       expected_coords,
     164           0 :       pat_blocked_col.coords(x));
     165          43 :     EXPECT_EQ(
     166             :       expected_unit_id,
     167           0 :       pat_blocked_col.unit_at(std::array<index_t, 1> { x }));
     168          43 :     EXPECT_EQ(
     169             :       expected_offset,
     170           0 :       pat_blocked_col.at(std::array<index_t, 1> { x }));
     171             :     auto glob_coords_col =
     172             :       pat_blocked_col.global(
     173          43 :         expected_unit_id, std::array<index_t, 1> { expected_offset });
     174          43 :     EXPECT_EQ(
     175             :       (std::array<index_t, 1> { expected_index }),
     176           0 :       glob_coords_col);
     177             :   }
     178             : }
     179             : 
     180          20 : TEST_F(BlockPatternTest, Distribute1DimCyclic)
     181             : {
     182           4 :   DASH_TEST_LOCAL_ONLY();
     183             :   typedef dash::default_index_t index_t;
     184             :   // Simple 1-dimensional cyclic partitioning:
     185             :   //
     186             :   // [ team 0 | team 1 | team 0 | team 1 | ... ]
     187           1 :   size_t team_size  = dash::Team::All().size();
     188           1 :   size_t block_size = dash::math::div_ceil(_num_elem, team_size);
     189           1 :   size_t local_cap  = block_size;
     190             :   dash::Pattern<1, dash::ROW_MAJOR> pat_cyclic_row(
     191           1 :       dash::SizeSpec<1>(_num_elem),
     192             :       dash::DistributionSpec<1>(dash::CYCLIC),
     193             :       dash::TeamSpec<1>(),
     194           3 :       dash::Team::All());
     195             :   // Column order must be irrelevant:
     196             :   dash::Pattern<1, dash::COL_MAJOR> pat_cyclic_col(
     197           1 :       dash::SizeSpec<1>(_num_elem),
     198             :       dash::DistributionSpec<1>(dash::CYCLIC),
     199             :       dash::TeamSpec<1>(),
     200           3 :       dash::Team::All());
     201           1 :   EXPECT_EQ(pat_cyclic_row.capacity(), _num_elem);
     202           1 :   EXPECT_EQ(pat_cyclic_row.blocksize(0), 1);
     203           1 :   EXPECT_EQ(pat_cyclic_row.local_capacity(), local_cap);
     204           1 :   EXPECT_EQ(pat_cyclic_col.capacity(), _num_elem);
     205           1 :   EXPECT_EQ(pat_cyclic_col.blocksize(0), 1);
     206           1 :   EXPECT_EQ(pat_cyclic_col.local_capacity(), local_cap);
     207             :   std::array<index_t, 1> expected_coords;
     208         251 :   for (int x = 0; x < _num_elem; ++x) {
     209         250 :     int expected_unit_id = x % team_size;
     210         250 :     int expected_offset  = x / team_size;
     211         250 :     int expected_index   = x;
     212         250 :     expected_coords[0]   = x;
     213             :     LOG_MESSAGE("x: %d, eu: %d, eo: %d",
     214             :       x, expected_unit_id, expected_offset);
     215             :     // Row major:
     216         250 :     EXPECT_EQ(
     217             :       expected_coords,
     218           0 :       pat_cyclic_row.coords(x));
     219         250 :     EXPECT_EQ(
     220             :       expected_unit_id,
     221           0 :       pat_cyclic_row.unit_at(std::array<index_t, 1> { x }));
     222         250 :     EXPECT_EQ(
     223             :       expected_offset,
     224           0 :       pat_cyclic_row.at(std::array<index_t, 1> { x }));
     225         250 :     EXPECT_EQ(
     226             :       (std::array<index_t, 1> { expected_index }),
     227             :       pat_cyclic_row.global(
     228           0 :         expected_unit_id, (std::array<index_t, 1> { expected_offset })));
     229             :     // Column major:
     230         250 :     EXPECT_EQ(
     231             :       expected_coords,
     232           0 :       pat_cyclic_col.coords(x));
     233         250 :     EXPECT_EQ(
     234             :       expected_unit_id,
     235           0 :       pat_cyclic_col.unit_at(std::array<index_t, 1> { x }));
     236         250 :     EXPECT_EQ(
     237             :       expected_offset,
     238           0 :       pat_cyclic_col.at(std::array<index_t, 1> { x }));
     239         250 :     EXPECT_EQ(
     240             :       (std::array<index_t, 1> { expected_index }),
     241             :       pat_cyclic_col.global(
     242           0 :         expected_unit_id, (std::array<index_t, 1> { expected_offset })));
     243             :   }
     244             : }
     245             : 
     246          20 : TEST_F(BlockPatternTest, Distribute1DimBlockcyclic)
     247             : {
     248           4 :   DASH_TEST_LOCAL_ONLY();
     249             :   typedef dash::default_index_t index_t;
     250             :   // Simple 1-dimensional blocked partitioning:
     251             :   //
     252             :   // [ team 0 | team 1 | team 0 | team 1 | ... ]
     253           1 :   size_t team_size  = dash::Team::All().size();
     254           1 :   size_t block_size = 23;
     255           1 :   size_t num_blocks = dash::math::div_ceil(_num_elem, block_size);
     256           1 :   size_t local_cap  = block_size *
     257           2 :                         dash::math::div_ceil(num_blocks, team_size);
     258             :   dash::Pattern<1, dash::ROW_MAJOR> pat_blockcyclic_row(
     259           1 :       dash::SizeSpec<1>(_num_elem),
     260           2 :       dash::DistributionSpec<1>(dash::BLOCKCYCLIC(block_size)),
     261             :       dash::TeamSpec<1>(),
     262           5 :       dash::Team::All());
     263             :   // Column order must be irrelevant:
     264             :   dash::Pattern<1, dash::COL_MAJOR> pat_blockcyclic_col(
     265           1 :       dash::SizeSpec<1>(_num_elem),
     266           2 :       dash::DistributionSpec<1>(dash::BLOCKCYCLIC(block_size)),
     267             :       dash::TeamSpec<1>(),
     268           5 :       dash::Team::All());
     269           1 :   EXPECT_EQ(pat_blockcyclic_row.capacity(), _num_elem);
     270           1 :   EXPECT_EQ(pat_blockcyclic_row.blocksize(0), block_size);
     271           1 :   EXPECT_EQ(pat_blockcyclic_row.local_capacity(), local_cap);
     272           1 :   EXPECT_EQ(pat_blockcyclic_col.capacity(), _num_elem);
     273           1 :   EXPECT_EQ(pat_blockcyclic_col.blocksize(0), block_size);
     274           1 :   EXPECT_EQ(pat_blockcyclic_col.local_capacity(), local_cap);
     275             :   LOG_MESSAGE("num elem: %d, block size: %lu, num blocks: %lu",
     276             :     _num_elem, block_size, num_blocks);
     277             :   std::array<index_t, 1> expected_coords;
     278         251 :   for (int x = 0; x < _num_elem; ++x) {
     279         250 :     int unit_id           = (x / block_size) % team_size;
     280         250 :     int block_index       = x / block_size;
     281         250 :     int block_base_offset = block_size * (block_index / team_size);
     282         250 :     int expected_unit_id  = block_index % team_size;
     283         250 :     int expected_offset   = (x % block_size) + block_base_offset;
     284         250 :     int expected_index    = x;
     285         250 :     expected_coords[0]    = x;
     286             :     LOG_MESSAGE("x: %d, eu: %d, eo: %d, bi: %d bbo: %d",
     287             :       x, expected_unit_id, expected_offset,
     288             :       block_index, block_base_offset);
     289             :     // Row major:
     290         250 :     EXPECT_EQ(
     291             :       expected_coords,
     292           0 :       pat_blockcyclic_row.coords(x));
     293         250 :     EXPECT_TRUE(
     294           0 :       pat_blockcyclic_row.is_local(x, unit_id));
     295         250 :     EXPECT_EQ(
     296             :       expected_unit_id,
     297           0 :       pat_blockcyclic_row.unit_at(std::array<index_t, 1> { x }));
     298         250 :     EXPECT_EQ(
     299             :       expected_offset,
     300           0 :       pat_blockcyclic_row.at(std::array<index_t, 1> { x }));
     301         250 :     EXPECT_EQ(
     302             :       (std::array<index_t, 1> { expected_index }),
     303             :       pat_blockcyclic_row.global(
     304           0 :         expected_unit_id, (std::array<index_t, 1> { expected_offset })));
     305             :     // Column major:
     306         250 :     EXPECT_EQ(
     307             :       expected_coords,
     308           0 :       pat_blockcyclic_col.coords(x));
     309         250 :     EXPECT_TRUE(
     310           0 :       pat_blockcyclic_col.is_local(x, unit_id));
     311         250 :     EXPECT_EQ(
     312             :       expected_unit_id,
     313           0 :       pat_blockcyclic_col.unit_at(std::array<index_t, 1> { x }));
     314         250 :     EXPECT_EQ(
     315             :       expected_offset,
     316           0 :       pat_blockcyclic_col.at(std::array<index_t, 1> { x }));
     317         250 :     EXPECT_EQ(
     318             :       (std::array<index_t, 1> { expected_index }),
     319             :       pat_blockcyclic_col.global(
     320           0 :         expected_unit_id, (std::array<index_t, 1> { expected_offset })));
     321             :   }
     322             : }
     323             : 
     324          20 : TEST_F(BlockPatternTest, Distribute2DimBlockedY)
     325             : {
     326           4 :   DASH_TEST_LOCAL_ONLY();
     327             :   typedef dash::default_index_t  index_t;
     328             :   typedef std::array<index_t, 2> coords_t;
     329             : 
     330             :   typedef dash::Pattern<2, dash::ROW_MAJOR>
     331             :     pattern_rowmajor_t;
     332             :   typedef dash::Pattern<2, dash::COL_MAJOR>
     333             :     pattern_colmajor_t;
     334             : 
     335             :   // 2-dimensional, blocked partitioning in first dimension:
     336             :   // Row major:
     337             :   // [ unit 0[0] | unit 0[1] | ... | unit 0[2] ]
     338             :   // [ unit 0[3] | unit 0[4] | ... | unit 0[5] ]
     339             :   // [ unit 1[0] | unit 1[1] | ... | unit 1[2] ]
     340             :   // [ unit 1[3] | unit 1[4] | ... | unit 1[5] ]
     341             :   // [                   ...                   ]
     342             :   // Column major:
     343             :   // [ unit 0[0] | unit 0[2] | ... | unit 0[4] ]
     344             :   // [ unit 0[1] | unit 0[3] | ... | unit 0[5] ]
     345             :   // [ unit 1[0] | unit 1[2] | ... | unit 1[4] ]
     346             :   // [ unit 1[1] | unit 1[3] | ... | unit 1[5] ]
     347             :   // [                   ...                   ]
     348           1 :   size_t team_size      = dash::Team::All().size();
     349           1 :   size_t extent_x       = 17;
     350           1 :   size_t extent_y       = 5 + team_size * 3;
     351           1 :   size_t size           = extent_x * extent_y;
     352             :   // Ceil division
     353           1 :   size_t block_size_x   = extent_x;
     354           1 :   size_t block_size_y   = dash::math::div_ceil(extent_y, team_size);
     355           1 :   size_t max_per_unit   = block_size_x * block_size_y;
     356           1 :   size_t overflow_bs_x  = extent_x % block_size_x;
     357           1 :   size_t overflow_bs_y  = extent_y % block_size_y;
     358             :   size_t underfill_bs_x = (overflow_bs_x == 0)
     359             :                           ? 0
     360           1 :                           : block_size_x - overflow_bs_x;
     361             :   size_t underfill_bs_y = (overflow_bs_y == 0)
     362             :                           ? 0
     363           1 :                           : block_size_y - overflow_bs_y;
     364             :   LOG_MESSAGE("ex: %d, ey: %d, bsx: %d, bsy: %d, mpu: %d",
     365             :       extent_y, extent_x,
     366             :       block_size_y, block_size_x,
     367             :       max_per_unit);
     368             :   pattern_rowmajor_t pat_blocked_row(
     369             :       dash::SizeSpec<2>(extent_y, extent_x),
     370             :       dash::DistributionSpec<2>(dash::BLOCKED, dash::NONE),
     371           1 :       dash::TeamSpec<2>(dash::Team::All()),
     372           2 :       dash::Team::All());
     373             :   pattern_colmajor_t pat_blocked_col(
     374             :       dash::SizeSpec<2>(extent_y, extent_x),
     375             :       dash::DistributionSpec<2>(dash::BLOCKED, dash::NONE),
     376           1 :       dash::TeamSpec<2>(dash::Team::All()),
     377           2 :       dash::Team::All());
     378             : 
     379           2 :   dash::test::print_pattern_mapping(
     380             :     "pattern.rowmajor.unit_at", pat_blocked_row, 1,
     381         289 :     [](const pattern_rowmajor_t & _pattern, int _x, int _y) -> dart_unit_t {
     382         289 :         return _pattern.unit_at(std::array<index_t, 2> {_x, _y});
     383           1 :     });
     384           2 :   dash::test::print_pattern_mapping(
     385             :     "pattern.rowmajor.local_index", pat_blocked_row, 3,
     386         289 :     [](const pattern_rowmajor_t & _pattern, int _x, int _y) -> index_t {
     387         289 :         return _pattern.local_index(std::array<index_t, 2> {_x, _y}).index;
     388           1 :     });
     389           2 :   dash::test::print_pattern_mapping(
     390             :     "pattern.colmajor.unit_at", pat_blocked_col, 1,
     391         289 :     [](const pattern_colmajor_t & _pattern, int _x, int _y) -> dart_unit_t {
     392         289 :         return _pattern.unit_at(std::array<index_t, 2> {_x, _y});
     393           1 :     });
     394           2 :   dash::test::print_pattern_mapping(
     395             :     "pattern.colmajor.local_index", pat_blocked_col, 3,
     396         289 :     [](const pattern_colmajor_t & _pattern, int _x, int _y) -> index_t {
     397         289 :         return _pattern.local_index(std::array<index_t, 2> {_x, _y}).index;
     398           1 :     });
     399             : 
     400           1 :   EXPECT_EQ(pat_blocked_row.capacity(), size);
     401           1 :   EXPECT_EQ(pat_blocked_row.local_capacity(), max_per_unit);
     402           1 :   EXPECT_EQ(pat_blocked_row.blocksize(1), block_size_x);
     403           1 :   EXPECT_EQ(pat_blocked_row.blocksize(0), block_size_y);
     404           1 :   EXPECT_EQ(pat_blocked_row.underfilled_blocksize(1), underfill_bs_x);
     405           1 :   EXPECT_EQ(pat_blocked_row.underfilled_blocksize(0), underfill_bs_y);
     406           1 :   EXPECT_EQ(pat_blocked_col.capacity(), size);
     407           1 :   EXPECT_EQ(pat_blocked_col.local_capacity(), max_per_unit);
     408           1 :   EXPECT_EQ(pat_blocked_col.blocksize(1), block_size_x);
     409           1 :   EXPECT_EQ(pat_blocked_col.blocksize(0), block_size_y);
     410           1 :   EXPECT_EQ(pat_blocked_col.underfilled_blocksize(1), underfill_bs_x);
     411           1 :   EXPECT_EQ(pat_blocked_col.underfilled_blocksize(0), underfill_bs_y);
     412             :   LOG_MESSAGE("block size: x: %d, y: %d",
     413             :     block_size_x, block_size_y);
     414          18 :   for (int x = 0; x < extent_x; ++x) {
     415         306 :     for (int y = 0; y < extent_y; ++y) {
     416             :       // Units might have empty local range, e.g. when distributing 41
     417             :       // elements to 8 units.
     418         289 :       int num_blocks_y              = dash::math::div_ceil(
     419         289 :                                         extent_y, block_size_y);
     420             :       // Subtract missing elements in last block if any:
     421         289 :       int underfill_y               = (y >= (num_blocks_y-1) *
     422             :                                             block_size_y)
     423             :                                       ? (block_size_y * num_blocks_y) -
     424             :                                         extent_y
     425         289 :                                       : 0;
     426             :       // Actual extent of block, adjusted for underfilled extent:
     427         289 :       int block_size_y_adj          = block_size_y - underfill_y;
     428         289 :       int expected_index_row_order  = (y * extent_x) + x;
     429         289 :       int expected_index_col_order  = (x * extent_y) + y;
     430         289 :       int expected_offset_row_order = expected_index_row_order % max_per_unit;
     431         578 :       int expected_offset_col_order = (y % block_size_y) + (x *
     432         578 :                                         block_size_y_adj);
     433         289 :       int expected_unit_id          = y / block_size_y;
     434         289 :       int local_x                   = x;
     435         289 :       int local_y                   = y % block_size_y;
     436             :       // Row major:
     437             :       LOG_MESSAGE("R %d,%d, eo:%d, ao:%d, ei:%d, bx:%d, by:%d, bya:%d",
     438             :         y, x,
     439             :         expected_offset_row_order,
     440             :         pat_blocked_row.at(std::array<index_t, 2> { y, x }),
     441             :         expected_index_row_order,
     442             :         block_size_x, block_size_y, block_size_y_adj);
     443         289 :       EXPECT_EQ(
     444             :         expected_unit_id,
     445           0 :         pat_blocked_row.unit_at(std::array<index_t, 2> { y, x }));
     446         289 :       EXPECT_EQ(
     447             :         expected_offset_row_order,
     448           0 :         pat_blocked_row.at(std::array<index_t, 2> { y, x }));
     449         289 :       EXPECT_EQ(
     450             :         (std::array<index_t, 2> { y, x }),
     451             :         pat_blocked_row.global(
     452             :           expected_unit_id,
     453           0 :           (std::array<index_t, 2> { local_y, local_x  })));
     454             :       // Col major:
     455             :       LOG_MESSAGE("C %d,%d, eo:%d, ao:%d, ei:%d, bx:%d, by:%d",
     456             :         y, x,
     457             :         expected_offset_col_order,
     458             :         pat_blocked_col.at(std::array<index_t, 2> { y, x }),
     459             :         expected_index_col_order,
     460             :         block_size_x, block_size_y);
     461         289 :       EXPECT_EQ(
     462             :         expected_unit_id,
     463           0 :         pat_blocked_col.unit_at(std::array<index_t, 2> { y, x }));
     464         289 :       EXPECT_EQ(
     465             :         expected_offset_col_order,
     466           0 :         pat_blocked_col.at(std::array<index_t, 2> { y, x }));
     467         289 :       EXPECT_EQ(
     468             :         (std::array<index_t, 2> { y, x }),
     469             :         pat_blocked_col.global(
     470             :           expected_unit_id,
     471           0 :           (std::array<index_t, 2> { local_y, local_x })));
     472             :     }
     473             :   }
     474             : }
     475             : 
     476          20 : TEST_F(BlockPatternTest, Distribute2DimBlockedX)
     477             : {
     478           4 :   DASH_TEST_LOCAL_ONLY();
     479             :   typedef dash::default_index_t index_t;
     480             :   // 2-dimensional, blocked partitioning in first dimension:
     481             :   //
     482             :   // [ team 0[0] | team 1[0] | team 2[0] | ... | team n-1 ]
     483             :   // [ team 0[1] | team 1[1] | team 2[1] | ... | team n-1 ]
     484             :   // [ team 0[2] | team 1[2] | team 2[2] | ... | team n-1 ]
     485             :   // [ team 0[3] | team 1[3] | team 2[3] | ... | team n-1 ]
     486             :   // [                       ...                          ]
     487           1 :   int team_size    = dash::Team::All().size();
     488           1 :   int extent_x     = 41;
     489           1 :   int extent_y     = 17;
     490           1 :   size_t size      = extent_x * extent_y;
     491             :   // Ceil division
     492           1 :   int block_size_x = dash::math::div_ceil(extent_x, team_size);
     493           1 :   int block_size_y = extent_y;
     494           1 :   int max_per_unit = block_size_x * block_size_y;
     495             :   dash::Pattern<2, dash::ROW_MAJOR> pat_blocked_row(
     496             :       dash::SizeSpec<2>(extent_x, extent_y),
     497             :       dash::DistributionSpec<2>(dash::BLOCKED, dash::NONE),
     498           1 :       dash::TeamSpec<2>(dash::Team::All()),
     499           2 :       dash::Team::All());
     500             :   dash::Pattern<2, dash::COL_MAJOR> pat_blocked_col(
     501             :       dash::SizeSpec<2>(extent_x, extent_y),
     502             :       dash::DistributionSpec<2>(dash::BLOCKED, dash::NONE),
     503           1 :       dash::TeamSpec<2>(dash::Team::All()),
     504           2 :       dash::Team::All());
     505           1 :   EXPECT_EQ(pat_blocked_row.capacity(), size);
     506           1 :   EXPECT_EQ(pat_blocked_row.local_capacity(), max_per_unit);
     507           1 :   EXPECT_EQ(pat_blocked_row.blocksize(0), block_size_x);
     508           1 :   EXPECT_EQ(pat_blocked_row.blocksize(1), block_size_y);
     509           1 :   EXPECT_EQ(pat_blocked_col.capacity(), size);
     510           1 :   EXPECT_EQ(pat_blocked_col.local_capacity(), max_per_unit);
     511           1 :   EXPECT_EQ(pat_blocked_col.blocksize(0), block_size_x);
     512           1 :   EXPECT_EQ(pat_blocked_col.blocksize(1), block_size_y);
     513          42 :   for (int x = 0; x < extent_x; ++x) {
     514         738 :     for (int y = 0; y < extent_y; ++y) {
     515             :       // Units might have empty local range, e.g. when distributing 41
     516             :       // elements to 8 units.
     517         697 :       int num_blocks_x              = dash::math::div_ceil(
     518         697 :                                         extent_x, block_size_x);
     519             :       // Subtract missing elements in last block if any:
     520         697 :       int underfill_x               = (x >= (num_blocks_x-1) *
     521             :                                         block_size_x)
     522         136 :                                       ? (block_size_x * num_blocks_x) -
     523             :                                         extent_x
     524         833 :                                       : 0;
     525             :       // Actual extent of block, adjusted for underfilled extent:
     526         697 :       int block_size_x_adj          = block_size_x - underfill_x;
     527         697 :       int expected_index_col_order  = (y * extent_x) + x;
     528         697 :       int expected_index_row_order  = (x * extent_y) + y;
     529        1394 :       int expected_offset_col_order = (x % block_size_x) +
     530        1394 :                                       (y * block_size_x_adj);
     531         697 :       int expected_offset_row_order = expected_index_row_order %
     532         697 :                                         max_per_unit;
     533         697 :       int expected_unit_id          = x / block_size_x;
     534         697 :       int local_x                   = x % block_size_x;
     535         697 :       int local_y                   = y;
     536             :       // Row major:
     537             :       LOG_MESSAGE("R %d,%d, eo:%d, ao:%d, nbx:%d, bx:%d, by:%d, bxa:%d",
     538             :         x, y,
     539             :         expected_offset_row_order,
     540             :         pat_blocked_row.at(std::array<index_t, 2> { x, y }),
     541             :         num_blocks_x,
     542             :         block_size_x, block_size_y, block_size_x_adj);
     543         697 :       EXPECT_EQ(
     544             :         expected_unit_id,
     545           0 :         pat_blocked_row.unit_at(std::array<index_t, 2> { x, y }));
     546         697 :       EXPECT_EQ(
     547             :         expected_offset_row_order,
     548           0 :         pat_blocked_row.at(std::array<index_t, 2> { x, y }));
     549         697 :       EXPECT_EQ(
     550             :         (std::array<index_t, 2> { x, y }),
     551             :         pat_blocked_row.global(
     552             :           expected_unit_id,
     553           0 :           (std::array<index_t, 2> { local_x, local_y })));
     554             :       // Col major:
     555             :       LOG_MESSAGE("C %d,%d, eo:%d, ao:%d, ei:%d, bx:%d, by:%d",
     556             :         x, y,
     557             :         expected_offset_col_order,
     558             :         pat_blocked_col.at(std::array<index_t, 2> { x, y }),
     559             :         expected_index_col_order,
     560             :         block_size_x, block_size_y);
     561         697 :       EXPECT_EQ(
     562             :         expected_unit_id,
     563           0 :         pat_blocked_col.unit_at(std::array<index_t, 2> { x, y }));
     564         697 :       EXPECT_EQ(
     565             :         expected_offset_col_order,
     566           0 :         pat_blocked_col.at(std::array<index_t, 2> { x, y }));
     567         697 :       EXPECT_EQ(
     568             :         (std::array<index_t, 2> { x, y }),
     569             :         pat_blocked_col.global(
     570             :           expected_unit_id,
     571           0 :           (std::array<index_t, 2> { local_x, local_y })));
     572             :     }
     573             :   }
     574             : }
     575             : 
     576          20 : TEST_F(BlockPatternTest, Distribute2DimBlockcyclicXY)
     577             : {
     578           7 :   DASH_TEST_LOCAL_ONLY();
     579             :   typedef dash::default_index_t  index_t;
     580             :   typedef std::array<index_t, 2> coords_t;
     581             :   // 2-dimensional, blocked partitioning in two dimensions:
     582             :   //
     583             :   // [ team 0[0] | team 1[0] | team 0[1] | team 1[1] ]
     584             :   // [ team 0[2] | team 1[2] | team 0[3] | team 1[3] ]
     585             :   // [ team 2[0] | team 3[0] | team 2[1] | team 3[1] ]
     586             :   // [ team 2[2] | team 3[2] | team 2[3] | team 3[3] ]
     587             :   // [                      ...                      ]
     588           1 :   int team_size    = dash::Team::All().size();
     589           1 :   if (team_size < 4) {
     590             :     LOG_MESSAGE("Skipping test Distribute2DimBlockcyclicXY, "
     591             :                 "at least 4 units nedded");
     592           0 :     return;
     593             :   }
     594           1 :   if (team_size % 2 != 0) {
     595             :     LOG_MESSAGE("Skipping test Distribute2DimBlockcyclicXY, "
     596             :                 "number of units must be multiple of 2");
     597           0 :     return;
     598             :   }
     599           1 :   size_t extent_x     = 5 + team_size;
     600           1 :   size_t extent_y     = 3 + team_size;
     601           1 :   size_t size         = extent_x * extent_y;
     602             :   // Ceil division
     603           1 :   size_t block_size_x = 3;
     604           1 :   size_t block_size_y = 2;
     605           1 :   size_t num_units_x  = team_size / 2;
     606           1 :   size_t num_units_y  = 2;
     607           1 :   size_t block_size   = block_size_x * block_size_y;
     608           1 :   size_t num_blocks_x = dash::math::div_ceil(extent_x, block_size_x);
     609           1 :   size_t num_blocks_y = dash::math::div_ceil(extent_y, block_size_y);
     610           2 :   size_t max_per_unit = dash::math::div_ceil(num_blocks_x, num_units_x) *
     611           2 :                         dash::math::div_ceil(num_blocks_y, num_units_y) *
     612           1 :                         block_size;
     613           1 :   dash::TeamSpec<2> ts(num_units_x, num_units_y);
     614           1 :   EXPECT_EQ_U(ts.size(), team_size);
     615           1 :   EXPECT_EQ_U(ts.rank(), 2);
     616             :   dash::Pattern<2, dash::ROW_MAJOR> pat_row(
     617             :       dash::SizeSpec<2>(extent_x, extent_y),
     618             :       dash::DistributionSpec<2>(
     619           2 :         dash::BLOCKCYCLIC(block_size_x),
     620           2 :         dash::BLOCKCYCLIC(block_size_y)),
     621             :       dash::TeamSpec<2>(num_units_x, num_units_y),
     622           3 :       dash::Team::All());
     623             :   dash::Pattern<2, dash::COL_MAJOR> pat_col(
     624             :       dash::SizeSpec<2>(extent_x, extent_y),
     625             :       dash::DistributionSpec<2>(
     626           2 :         dash::BLOCKCYCLIC(block_size_x),
     627           2 :         dash::BLOCKCYCLIC(block_size_y)),
     628             :       dash::TeamSpec<2>(num_units_x, num_units_y),
     629           3 :       dash::Team::All());
     630             : 
     631             :   typedef decltype(pat_row) pattern_rmaj_t;
     632             :   typedef decltype(pat_col) pattern_cmaj_t;
     633             : 
     634           1 :   if (dash::myid() == 0) {
     635           2 :     dash::test::print_pattern_mapping(
     636             :       "pattern.row-major.local_index", pat_row, 6,
     637          63 :       [](const pattern_rmaj_t & _pattern, int _x, int _y) -> std::string {
     638          63 :           auto lpos    = _pattern.local_index(coords_t {_x, _y});
     639          63 :           auto unit    = lpos.unit;
     640          63 :           auto lindex  = lpos.index;
     641         126 :           std::ostringstream ss;
     642          63 :           ss << "u" << unit << "("
     643         126 :              << std::setw(2) << lindex
     644          63 :              << ")";
     645         126 :           return ss.str();
     646           1 :       });
     647           2 :     dash::test::print_pattern_mapping(
     648             :       "pattern.col-major.local_index", pat_col, 6,
     649          63 :       [](const pattern_cmaj_t & _pattern, int _x, int _y) -> std::string {
     650          63 :           auto lpos    = _pattern.local_index(coords_t {_x, _y});
     651          63 :           auto unit    = lpos.unit;
     652          63 :           auto lindex  = lpos.index;
     653         126 :           std::ostringstream ss;
     654          63 :           ss << "u" << unit << "("
     655         126 :              << std::setw(2) << lindex
     656          63 :              << ")";
     657         126 :           return ss.str();
     658           1 :       });
     659             :   }
     660             : 
     661           1 :   EXPECT_EQ_U(pat_row.team().size(), team_size);
     662           1 :   EXPECT_EQ_U(pat_row.teamspec().size(), team_size);
     663           1 :   EXPECT_EQ_U(pat_row.capacity(), size);
     664           1 :   EXPECT_EQ_U(pat_row.local_capacity(), max_per_unit);
     665           1 :   EXPECT_EQ_U(pat_row.blocksize(0), block_size_x);
     666           1 :   EXPECT_EQ_U(pat_row.blocksize(1), block_size_y);
     667           1 :   EXPECT_EQ_U(pat_col.team().size(), team_size);
     668           1 :   EXPECT_EQ_U(pat_col.teamspec().size(), team_size);
     669           1 :   EXPECT_EQ_U(pat_col.capacity(), size);
     670           1 :   EXPECT_EQ_U(pat_col.local_capacity(), max_per_unit);
     671           1 :   EXPECT_EQ_U(pat_col.blocksize(0), block_size_x);
     672           1 :   EXPECT_EQ_U(pat_col.blocksize(1), block_size_y);
     673          10 :   for (int x = 0; x < static_cast<int>(extent_x); ++x) {
     674          72 :     for (int y = 0; y < static_cast<int>(extent_y); ++y) {
     675             :       // Units might have empty local range, e.g. when distributing 41
     676             :       // elements to 8 units.
     677             :       // Subtract missing elements in last block if any:
     678          63 :       int underfill_x               = (x >= static_cast<int>(
     679          63 :                                              (num_blocks_x-1) * block_size_x))
     680             :                                       ? (block_size_x * num_blocks_x) -
     681             :                                         extent_x
     682          63 :                                       : 0;
     683             :       // Actual extent of block, adjusted for underfilled extent:
     684          63 :       int block_size_x_adj          = block_size_x - underfill_x;
     685          63 :       int expected_offset_row_order = 0;
     686          63 :       int expected_offset_col_order = 0;
     687          63 :       int block_coord_x             = (x / block_size_x) % num_units_x;
     688          63 :       int block_coord_y             = (y / block_size_y) % num_units_y;
     689             :       int expected_unit_id          = block_coord_x * num_units_y +
     690          63 :                                       block_coord_y;
     691             : //    int local_x                   = x % block_size_x;
     692             : //    int local_y                   = y;
     693             :       // Row major:
     694             :       LOG_MESSAGE("R %d,%d, eo:%d, ao:%d, nbx:%lu, bx:%lu, by:%lu, bxa:%d",
     695             :         x, y,
     696             :         expected_offset_row_order,
     697             :         pat_row.at(std::array<index_t, 2> { x, y }),
     698             :         num_blocks_x,
     699             :         block_size_x, block_size_y, block_size_x_adj);
     700          63 :       EXPECT_EQ(
     701             :         expected_unit_id,
     702           0 :         pat_row.unit_at(std::array<index_t, 2> { x, y }));
     703             : #if DEACT
     704             :       EXPECT_EQ(
     705             :         expected_offset_row_order,
     706             :         pat_row.at(std::array<index_t, 2> { x, y }));
     707             :       EXPECT_EQ(
     708             :         (std::array<index_t, 2> { x, y }),
     709             :         pat_row.global(
     710             :           expected_unit_id,
     711             :           (std::array<index_t, 2> { local_x, local_y })));
     712             : #endif
     713             :       // Col major:
     714             :       LOG_MESSAGE("C %d,%d, eo:%d, ao:%d, bx:%lu, by:%lu",
     715             :         x, y,
     716             :         expected_offset_col_order,
     717             :         pat_col.at(std::array<index_t, 2> { x, y }),
     718             :         block_size_x, block_size_y);
     719          63 :       EXPECT_EQ(
     720             :         expected_unit_id,
     721           0 :         pat_col.unit_at(std::array<index_t, 2> { x, y }));
     722             : #if DEACT
     723             :       EXPECT_EQ(
     724             :         expected_offset_col_order,
     725             :         pat_col.at(std::array<index_t, 2> { x, y }));
     726             :       EXPECT_EQ(
     727             :         (std::array<index_t, 2> { x, y }),
     728             :         pat_col.global(
     729             :           expected_unit_id,
     730             :           (std::array<index_t, 2> { local_x, local_y })));
     731             : #endif
     732             :     }
     733             :   }
     734             : }
     735             : 
     736          20 : TEST_F(BlockPatternTest, Distribute2DimCyclicX)
     737             : {
     738           4 :   DASH_TEST_LOCAL_ONLY();
     739             :   typedef dash::default_index_t index_t;
     740             :   // 2-dimensional, blocked partitioning in first dimension:
     741             :   //
     742             :   // [ team 0[0] | team 1[0] | team 0[1] | team 1[1] | ... ]
     743             :   // [ team 0[2] | team 1[2] | team 0[3] | team 1[3] | ... ]
     744             :   // [ team 0[4] | team 1[4] | team 0[5] | team 1[5] | ... ]
     745             :   // [ team 0[6] | team 1[6] | team 0[7] | team 1[7] | ... ]
     746             :   // [                        ...                          ]
     747           1 :   int team_size      = dash::Team::All().size();
     748             :   // Choose 'inconvenient' extents:
     749           1 :   int extent_x       = team_size + 7;
     750           1 :   int extent_y       = 23;
     751           1 :   size_t size        = extent_x * extent_y;
     752           1 :   int block_size_x   = 1;
     753           1 :   int max_per_unit_x = dash::math::div_ceil(extent_x, team_size);
     754           1 :   int block_size_y   = extent_y;
     755           1 :   int max_per_unit   = max_per_unit_x * block_size_y;
     756             :   LOG_MESSAGE("ex: %d, ey: %d, bsx: %d, bsy: %d, mpx: %d, mpu: %d",
     757             :       extent_x, extent_y,
     758             :       block_size_x, block_size_y,
     759             :       max_per_unit_x, max_per_unit);
     760             :   dash::Pattern<2, dash::ROW_MAJOR> pat_cyclic_row(
     761             :       dash::SizeSpec<2>(extent_x, extent_y),
     762             :       dash::DistributionSpec<2>(dash::CYCLIC, dash::NONE),
     763           1 :       dash::TeamSpec<2>(dash::Team::All()),
     764           2 :       dash::Team::All());
     765             :   dash::Pattern<2, dash::COL_MAJOR> pat_cyclic_col(
     766             :       dash::SizeSpec<2>(extent_x, extent_y),
     767             :       dash::DistributionSpec<2>(dash::CYCLIC, dash::NONE),
     768           1 :       dash::TeamSpec<2>(dash::Team::All()),
     769           2 :       dash::Team::All());
     770           1 :   EXPECT_EQ(pat_cyclic_row.capacity(), size);
     771           1 :   EXPECT_EQ(pat_cyclic_row.local_capacity(), max_per_unit);
     772           1 :   EXPECT_EQ(pat_cyclic_row.blocksize(0), block_size_x);
     773           1 :   EXPECT_EQ(pat_cyclic_row.blocksize(1), block_size_y);
     774           1 :   EXPECT_EQ(pat_cyclic_col.capacity(), size);
     775           1 :   EXPECT_EQ(pat_cyclic_col.local_capacity(), max_per_unit);
     776           1 :   EXPECT_EQ(pat_cyclic_col.blocksize(0), block_size_x);
     777           1 :   EXPECT_EQ(pat_cyclic_col.blocksize(1), block_size_y);
     778             :   // number of overflow blocks, e.g. 7 elements, 3 teams -> 1
     779           1 :   int num_overflow_blocks = extent_x % team_size;
     780          12 :   for (int x = 0; x < extent_x; ++x) {
     781         264 :     for (int y = 0; y < extent_y; ++y) {
     782         253 :       int unit_id                   = x % team_size;
     783         253 :       int min_blocks_x              = extent_x / team_size;
     784         253 :       int num_add_blocks_x          = extent_x % team_size;
     785         253 :       int num_blocks_unit_x         = min_blocks_x;
     786         253 :       if (unit_id < num_add_blocks_x) {
     787         207 :         num_blocks_unit_x++;
     788             :       }
     789             : //    int expected_index_row_order  = (y * extent_x) + x;
     790             : //    int expected_index_col_order  = (x * extent_y) + y;
     791         253 :       int expected_unit_id          = x % team_size;
     792         506 :       int expected_offset_col_order = (y * num_blocks_unit_x) +
     793         506 :                                       x / team_size;
     794         253 :       int expected_offset_row_order = ((x / team_size) * extent_y) + y;
     795         253 :       int local_x                   = x / team_size;
     796         253 :       int local_y                   = y;
     797             :       auto glob_coords_row =
     798             :         pat_cyclic_row.global(
     799             :           expected_unit_id,
     800         253 :           std::array<index_t, 2> { local_x, local_y });
     801             :       auto glob_coords_col =
     802             :         pat_cyclic_col.global(
     803             :           expected_unit_id,
     804         253 :           std::array<index_t, 2> { local_x, local_y });
     805             :       // Row major:
     806             :       LOG_MESSAGE("R x: %d, y: %d, eo: %d, ao: %d, of: %d, nbu: %d",
     807             :         x, y,
     808             :         expected_offset_row_order,
     809             :         pat_cyclic_row.at(std::array<index_t, 2> { x, y }),
     810             :         num_overflow_blocks,
     811             :         num_blocks_unit_x);
     812         253 :       EXPECT_EQ(
     813             :         expected_unit_id,
     814           0 :         pat_cyclic_row.unit_at(std::array<index_t, 2> { x, y }));
     815         253 :       EXPECT_EQ(
     816             :         expected_offset_row_order,
     817           0 :         pat_cyclic_row.at(std::array<index_t, 2> { x, y }));
     818         253 :       EXPECT_EQ(
     819             :         (std::array<index_t, 2> { x, y }),
     820           0 :         glob_coords_row);
     821             :       // Col major:
     822             :       LOG_MESSAGE("C x: %d, y: %d, eo: %d, ao: %d, of: %d",
     823             :         x, y,
     824             :         expected_offset_col_order,
     825             :         pat_cyclic_col.at(std::array<index_t, 2> { x, y }),
     826             :         num_overflow_blocks);
     827         253 :       EXPECT_EQ(
     828             :         expected_unit_id,
     829           0 :         pat_cyclic_col.unit_at(std::array<index_t, 2> { x, y }));
     830         253 :       EXPECT_EQ(
     831             :         expected_offset_col_order,
     832           0 :         pat_cyclic_col.at(std::array<index_t, 2> { x, y }));
     833         253 :       EXPECT_EQ(
     834             :         (std::array<index_t, 2> { x, y }),
     835           0 :         glob_coords_col);
     836             :     }
     837             :   }
     838             : }
     839             : 
     840          20 : TEST_F(BlockPatternTest, Distribute3DimBlockcyclicX)
     841             : {
     842           7 :   DASH_TEST_LOCAL_ONLY();
     843             :   typedef dash::default_index_t index_t;
     844             :   // 2-dimensional, blocked partitioning in first dimension:
     845             :   //
     846             :   // [ team 0[0] | team 1[0] | team 0[1] | team 1[1] | ... ]
     847             :   // [ team 0[2] | team 1[2] | team 0[3] | team 1[3] | ... ]
     848             :   // [ team 0[4] | team 1[4] | team 0[5] | team 1[5] | ... ]
     849             :   // [ team 0[6] | team 1[6] | team 0[7] | team 1[7] | ... ]
     850             :   // [                        ...                          ]
     851           1 :   size_t team_size    = dash::Team::All().size();
     852             :   // Choose 'inconvenient' extents:
     853           1 :   size_t extent_x     = 19 + team_size;
     854           1 :   size_t extent_y     = 51;
     855           1 :   size_t extent_z     = 3;
     856           1 :   size_t size         = extent_x * extent_y * extent_z;
     857           1 :   size_t block_size_x = 2;
     858           1 :   size_t num_blocks_x    = dash::math::div_ceil(extent_x, block_size_x);
     859           1 :   size_t max_per_unit_x  = block_size_x *
     860           2 :                            dash::math::div_ceil(num_blocks_x, team_size);
     861           1 :   size_t block_size_y    = extent_y;
     862           1 :   size_t block_size_z    = extent_z;
     863           1 :   size_t max_per_unit    = max_per_unit_x * block_size_y * block_size_z;
     864             :   LOG_MESSAGE("ex: %lu, ey: %lu, ez: %lu, bsx: %lu, bsy: %lu, "
     865             :               "mpx: %lu, mpu: %lu",
     866             :               extent_x, extent_y, extent_z,
     867             :               block_size_x, block_size_y,
     868             :               max_per_unit_x, max_per_unit);
     869             :   dash::Pattern<3, dash::ROW_MAJOR> pat_blockcyclic_row(
     870             :       dash::SizeSpec<3>(extent_x, extent_y, extent_z),
     871           2 :       dash::DistributionSpec<3>(dash::BLOCKCYCLIC(block_size_x),
     872             :                                 dash::NONE,
     873             :                                 dash::NONE),
     874           1 :       dash::TeamSpec<3>(dash::Team::All()),
     875           4 :       dash::Team::All());
     876             :   dash::Pattern<3, dash::COL_MAJOR> pat_blockcyclic_col(
     877             :       dash::SizeSpec<3>(extent_x, extent_y, extent_z),
     878           2 :       dash::DistributionSpec<3>(dash::BLOCKCYCLIC(block_size_x),
     879             :                                 dash::NONE,
     880             :                                 dash::NONE),
     881           1 :       dash::TeamSpec<3>(dash::Team::All()),
     882           4 :       dash::Team::All());
     883           1 :   ASSERT_EQ(pat_blockcyclic_row.capacity(), size);
     884           1 :   ASSERT_EQ(pat_blockcyclic_row.local_capacity(), max_per_unit);
     885           1 :   ASSERT_EQ(pat_blockcyclic_row.blocksize(0), block_size_x);
     886           1 :   ASSERT_EQ(pat_blockcyclic_row.blocksize(1), block_size_y);
     887           1 :   ASSERT_EQ(pat_blockcyclic_row.blocksize(2), block_size_z);
     888           1 :   ASSERT_EQ(pat_blockcyclic_col.capacity(), size);
     889           1 :   ASSERT_EQ(pat_blockcyclic_col.local_capacity(), max_per_unit);
     890           1 :   ASSERT_EQ(pat_blockcyclic_col.blocksize(0), block_size_x);
     891           1 :   ASSERT_EQ(pat_blockcyclic_col.blocksize(1), block_size_y);
     892           1 :   ASSERT_EQ(pat_blockcyclic_col.blocksize(2), block_size_z);
     893             :   // number of overflow blocks, e.g. 7 elements, 3 teams -> 1
     894             : //int num_overflow_blocks = extent_x % team_size;
     895          24 :   for (int x = 0; x < static_cast<int>(extent_x); ++x) {
     896        1196 :     for (int y = 0; y < static_cast<int>(extent_y); ++y) {
     897        4692 :       for (int z = 0; z < static_cast<int>(extent_z); ++z) {
     898        3519 :         int unit_id                   = (x / block_size_x) % team_size;
     899        3519 :         int num_blocks_x              = dash::math::div_ceil(
     900        3519 :                                           extent_x, block_size_x);
     901        3519 :         int min_blocks_x              = dash::math::div_ceil(
     902        3519 :                                           extent_x, block_size_x) /
     903        3519 :                                         team_size;
     904        3519 :         int num_add_blocks_x          = num_blocks_x % team_size;
     905        3519 :         int overflow_block_size_x     = extent_x % block_size_x;
     906        3519 :         int num_blocks_unit_x         = min_blocks_x;
     907        3519 :         int num_add_elem_x            = 0;
     908        3519 :         int block_offset_x            = x / block_size_x;
     909        3519 :         int last_block_unit           = (num_blocks_x % team_size == 0)
     910             :                                         ? team_size-1
     911        3519 :                                         : (num_blocks_x % team_size) - 1;
     912        3519 :         if (unit_id < num_add_blocks_x) {
     913           0 :           num_blocks_unit_x++;
     914           0 :           num_add_elem_x += block_size_x;
     915             :         }
     916        3519 :         if (unit_id == last_block_unit) {
     917         765 :           if (overflow_block_size_x > 0) {
     918         765 :             num_add_elem_x -= block_size_x - overflow_block_size_x;
     919             :           }
     920             :         }
     921             :         int local_extent_x            = (min_blocks_x * block_size_x) +
     922        3519 :                                         num_add_elem_x;
     923        3519 :         int local_block_index_x       = block_offset_x / team_size;
     924        3519 :         int expected_index_col_order  = (z * extent_y * extent_x) +
     925        3519 :                                         (y * extent_x) + x;
     926        3519 :         int expected_index_row_order  = (x * extent_y * extent_z) +
     927        3519 :                                         (y * extent_z) + z;
     928        3519 :         int expected_unit_id          = (x / block_size_x) % team_size;
     929             :         int local_index_x             = (local_block_index_x *
     930             :                                           block_size_x) +
     931        3519 :                                         (x % block_size_x);
     932             :         int expected_offset_col_order = local_index_x +
     933        3519 :                                         (y * local_extent_x) +
     934        3519 :                                         (z * local_extent_x * extent_y);
     935             :         int expected_offset_row_order = z +
     936             :                                         (y * extent_z) +
     937        3519 :                                         (local_index_x *
     938        3519 :                                           extent_y * extent_z);
     939        3519 :         int local_x                   = local_index_x;
     940        3519 :         int local_y                   = y;
     941        3519 :         int local_z                   = z;
     942             :         auto glob_coords_row =
     943             :           pat_blockcyclic_row.global(
     944             :             expected_unit_id,
     945        3519 :             std::array<index_t, 3> { local_x, local_y, local_z });
     946             :         auto glob_coords_col =
     947             :           pat_blockcyclic_col.global(
     948             :             expected_unit_id,
     949        3519 :             std::array<index_t, 3> { local_x, local_y, local_z });
     950             :         // Row major:
     951             :         LOG_MESSAGE("R %d,%d,%d, u:%d, nbu:%d, nbx:%d, box:%d, lbox:%d, "
     952             :                     "na:%d, lex:%d, lx:%d",
     953             :           x, y, z,
     954             :           unit_id,
     955             :           num_blocks_unit_x,
     956             :           num_blocks_x,
     957             :           block_offset_x,
     958             :           local_block_index_x,
     959             :           num_add_elem_x,
     960             :           local_extent_x,
     961             :           local_index_x);
     962        3519 :         EXPECT_EQ(
     963             :           expected_unit_id,
     964           0 :           pat_blockcyclic_row.unit_at(std::array<index_t, 3> { x,y,z }));
     965        3519 :         EXPECT_TRUE(
     966             :           pat_blockcyclic_row.is_local(
     967             :             expected_index_row_order,
     968           0 :             unit_id));
     969        3519 :         EXPECT_EQ(
     970             :           expected_offset_row_order,
     971           0 :           pat_blockcyclic_row.at(std::array<index_t, 3> { x,y,z }));
     972        3519 :         EXPECT_EQ(
     973             :           (std::array<index_t, 3> { x, y, z }),
     974           0 :           glob_coords_row);
     975             :         // Col major:
     976             :         LOG_MESSAGE("C %d,%d,%d, u:%d, nbu:%d, nbx:%d, box:%d, lbox:%d, "
     977             :                     "na:%d, lex:%d, lx:%d",
     978             :           x, y, z,
     979             :           unit_id,
     980             :           num_blocks_unit_x,
     981             :           num_blocks_x,
     982             :           block_offset_x,
     983             :           local_block_index_x,
     984             :           num_add_elem_x,
     985             :           local_extent_x,
     986             :           local_index_x);
     987        3519 :         EXPECT_EQ(
     988             :           expected_unit_id,
     989           0 :           pat_blockcyclic_col.unit_at(std::array<index_t, 3> { x,y,z }));
     990        3519 :         EXPECT_TRUE(
     991             :           pat_blockcyclic_col.is_local(
     992             :             expected_index_col_order,
     993           0 :             unit_id));
     994        3519 :         EXPECT_EQ(
     995             :           expected_offset_col_order,
     996           0 :           pat_blockcyclic_col.at(std::array<index_t, 3> { x,y,z }));
     997        3519 :         EXPECT_EQ(
     998             :           (std::array<index_t, 3> { x, y, z }),
     999           0 :           glob_coords_col);
    1000             :       }
    1001             :     }
    1002             :   }
    1003             : }
    1004             : 
    1005          20 : TEST_F(BlockPatternTest, LocalExtents2DimCyclicX)
    1006             : {
    1007             :   // Must be run on all units as local extents differ
    1008             : 
    1009             :   // 2-dimensional, cyclic partitioning in first dimension:
    1010             :   //
    1011             :   // [ team 0[0] | team 1[0] | team 0[1] | team 1[1] | ... ]
    1012             :   // [ team 0[2] | team 1[2] | team 0[3] | team 1[3] | ... ]
    1013             :   // [ team 0[4] | team 1[4] | team 0[5] | team 1[5] | ... ]
    1014             :   // [ team 0[6] | team 1[6] | team 0[7] | team 1[7] | ... ]
    1015             :   // [                        ...                          ]
    1016           4 :   int team_size      = dash::Team::All().size();
    1017             :   // Two blocks for every unit, plus one block
    1018           4 :   int extent_x       = (2 * team_size) + 1;
    1019           4 :   int extent_y       = 41;
    1020           4 :   int block_size_x   = 1;
    1021           4 :   int block_size_y   = extent_y;
    1022             : //int overflow_bs_x  = 0;
    1023             : //int overflow_bs_y  = 0;
    1024           4 :   int underfill_bs_x = 0;
    1025           4 :   int underfill_bs_y = 0;
    1026             : //size_t size        = extent_x * extent_y;
    1027           4 :   int max_per_unit_x = dash::math::div_ceil(extent_x, team_size);
    1028           4 :   int max_per_unit   = max_per_unit_x * block_size_y;
    1029             :   // Unit 0 should have 1 additional block assigned:
    1030           4 :   int local_extent_x = (dash::myid() == 0)
    1031             :                          ? 3
    1032           4 :                          : 2;
    1033           4 :   int local_extent_y = extent_y;
    1034             :   LOG_MESSAGE("ex: %d, ey: %d, bsx: %d, bsy: %d, mpx: %d, mpu: %d",
    1035             :       extent_x, extent_y,
    1036             :       block_size_x, block_size_y,
    1037             :       max_per_unit_x, max_per_unit);
    1038             :   dash::Pattern<2, dash::ROW_MAJOR> pat_cyclic_row(
    1039             :       dash::SizeSpec<2>(extent_x, extent_y),
    1040             :       dash::DistributionSpec<2>(dash::CYCLIC, dash::NONE),
    1041           4 :       dash::TeamSpec<2>(dash::Team::All()),
    1042           8 :       dash::Team::All());
    1043             :   dash::Pattern<2, dash::COL_MAJOR> pat_cyclic_col(
    1044             :       dash::SizeSpec<2>(extent_x, extent_y),
    1045             :       dash::DistributionSpec<2>(dash::CYCLIC, dash::NONE),
    1046           4 :       dash::TeamSpec<2>(dash::Team::All()),
    1047           8 :       dash::Team::All());
    1048             :   // Row major:
    1049           4 :   EXPECT_EQ(pat_cyclic_col.underfilled_blocksize(0), underfill_bs_x);
    1050           4 :   EXPECT_EQ(pat_cyclic_col.underfilled_blocksize(1), underfill_bs_y);
    1051           4 :   ASSERT_EQ(pat_cyclic_row.local_extent(0), local_extent_x);
    1052           4 :   ASSERT_EQ(pat_cyclic_row.local_extent(1), local_extent_y);
    1053           4 :   EXPECT_EQ(pat_cyclic_row.local_size(),
    1054           0 :             local_extent_x * local_extent_y);
    1055             :   // Col major:
    1056           4 :   EXPECT_EQ(pat_cyclic_col.underfilled_blocksize(0), underfill_bs_x);
    1057           4 :   EXPECT_EQ(pat_cyclic_col.underfilled_blocksize(1), underfill_bs_y);
    1058           4 :   ASSERT_EQ(pat_cyclic_col.local_extent(0), local_extent_x);
    1059           4 :   ASSERT_EQ(pat_cyclic_col.local_extent(1), local_extent_y);
    1060           4 :   EXPECT_EQ(pat_cyclic_col.local_size(),
    1061           0 :             local_extent_x * local_extent_y);
    1062             : }
    1063             : 
    1064          20 : TEST_F(BlockPatternTest, LocalExtents2DimBlockcyclicY)
    1065             : {
    1066             :   // Must be run on all units as local extents differ
    1067             : 
    1068             :   // 2-dimensional, blocked partitioning in second dimension:
    1069             :   // Row major:
    1070             :   // [ team 0[0] | team 0[1] | ... | team 0[2] ]
    1071             :   // [ team 0[3] | team 0[4] | ... | team 0[5] ]
    1072             :   // [ team 1[0] | team 1[1] | ... | team 1[2] ]
    1073             :   // [ team 1[3] | team 1[4] | ... | team 1[5] ]
    1074             :   // [                   ...                   ]
    1075             :   // Column major:
    1076             :   // [ team 0[0] | team 0[2] | ... | team 0[4] ]
    1077             :   // [ team 0[1] | team 0[3] | ... | team 0[5] ]
    1078             :   // [ team 1[0] | team 1[2] | ... | team 1[4] ]
    1079             :   // [ team 1[1] | team 1[3] | ... | team 1[5] ]
    1080             :   // [                   ...                   ]
    1081             :   //
    1082             :   // For units 0..n:
    1083             :   // - unit n has no additional block
    1084             :   // - unit n-1 has additional block with 1 extent smaller than
    1085             :   //   regular block size
    1086             :   // - unit n-2 has additional block with regular block size
    1087             :   // - all other units have no additional block
    1088           4 :   int team_size      = dash::Team::All().size();
    1089           4 :   int extent_x       = 41;
    1090           4 :   int block_size_y   = 3;
    1091             :   // Last block is 1 extent smaller:
    1092           4 :   int underfill_bs_x = 0;
    1093           4 :   int underfill_bs_y = 1;
    1094             : //int overflow_bs_x  = 0;
    1095             : //int overflow_bs_y  = block_size_y - underfill_bs_y;
    1096             :   // Two blocks for every unit, plus one additional block for
    1097             :   // half of the units:
    1098           4 :   int num_add_blocks = dash::math::div_ceil(team_size, 2);
    1099           4 :   int min_blocks_y   = 2 * team_size;
    1100           4 :   int num_blocks_y   = min_blocks_y + num_add_blocks;
    1101           4 :   int extent_y       = (num_blocks_y * block_size_y) - underfill_bs_y;
    1102           4 :   int block_size_x   = extent_x;
    1103             :   // First half of team should have 1 additional block assigned:
    1104           4 :   int local_extent_x = extent_x;
    1105           4 :   int local_min_ex_y = (min_blocks_y / team_size) * block_size_y;
    1106           4 :   int local_extent_y = local_min_ex_y;
    1107           4 :   if (dash::myid() < num_add_blocks) {
    1108             :     // Unit has additional block:
    1109           2 :     local_extent_y += block_size_y;
    1110           2 :     if (dash::myid() == num_add_blocks - 1) {
    1111             :       // Unit has additional underfilled block:
    1112           1 :       local_extent_y -= underfill_bs_y;
    1113             :     }
    1114             :   }
    1115             :   LOG_MESSAGE("ex: %d, ey: %d, bsx: %d, bsy: %d, nby: %d, "
    1116             :               "aby: %d, lex: %d, ley: %d",
    1117             :       extent_x, extent_y,
    1118             :       block_size_x, block_size_y,
    1119             :       num_blocks_y, num_add_blocks,
    1120             :       local_extent_x, local_extent_y);
    1121             :   dash::Pattern<2, dash::ROW_MAJOR> pat_blockcyclic_row(
    1122             :       dash::SizeSpec<2>(extent_y, extent_x),
    1123             :       dash::DistributionSpec<2>(
    1124           8 :         dash::BLOCKCYCLIC(block_size_y), dash::NONE),
    1125           4 :       dash::TeamSpec<2>(dash::Team::All()),
    1126          16 :       dash::Team::All());
    1127             :   dash::Pattern<2, dash::COL_MAJOR> pat_blockcyclic_col(
    1128             :       dash::SizeSpec<2>(extent_y, extent_x),
    1129             :       dash::DistributionSpec<2>(
    1130           8 :         dash::BLOCKCYCLIC(block_size_y), dash::NONE),
    1131           4 :       dash::TeamSpec<2>(dash::Team::All()),
    1132          16 :       dash::Team::All());
    1133             :   // Row major:
    1134           4 :   EXPECT_EQ(pat_blockcyclic_col.underfilled_blocksize(1), underfill_bs_x);
    1135           4 :   EXPECT_EQ(pat_blockcyclic_col.underfilled_blocksize(0), underfill_bs_y);
    1136           4 :   ASSERT_EQ(pat_blockcyclic_row.local_extent(1), local_extent_x);
    1137           4 :   ASSERT_EQ(pat_blockcyclic_row.local_extent(0), local_extent_y);
    1138           4 :   EXPECT_EQ(pat_blockcyclic_row.local_size(),
    1139           0 :             local_extent_x * local_extent_y);
    1140             :   // Col major:
    1141           4 :   EXPECT_EQ(pat_blockcyclic_col.underfilled_blocksize(1), underfill_bs_x);
    1142           4 :   EXPECT_EQ(pat_blockcyclic_col.underfilled_blocksize(0), underfill_bs_y);
    1143           4 :   ASSERT_EQ(pat_blockcyclic_col.local_extent(1), local_extent_x);
    1144           4 :   ASSERT_EQ(pat_blockcyclic_col.local_extent(0), local_extent_y);
    1145           4 :   EXPECT_EQ(pat_blockcyclic_col.local_size(),
    1146           0 :             local_extent_x * local_extent_y);
    1147          12 : }
    1148             : 

Generated by: LCOV version 1.12