LCOV - code coverage report
Current view: top level - test - GlobStencilIterTest.cc (source / functions) Hit Total Coverage
Test: coverage.info.cleaned Lines: 187 189 98.9 %
Date: 2016-06-29 12:30:40 Functions: 11 11 100.0 %

          Line data    Source code
       1             : #include <array>
       2             : #include <string>
       3             : #include <numeric>
       4             : #include <functional>
       5             : 
       6             : #include <libdash.h>
       7             : 
       8             : #include "TestBase.h"
       9             : #include "GlobStencilIterTest.h"
      10             : 
      11             : 
      12             : template<
      13             :   typename ValueType,
      14             :   typename FwdIt >
      15           6 : void print_region(
      16             :   const std::string & name,
      17             :   const FwdIt       & begin,
      18             :   const FwdIt       & end)
      19             : {
      20          12 :   std::vector<ValueType> values;
      21          44 :   for (auto h_it = begin; h_it != end; ++h_it) {
      22          38 :     ValueType v = *h_it;
      23          38 :     values.push_back(v);
      24             :   }
      25          44 :   for (int i = 0; i < values.size(); ++i) {
      26          38 :     ValueType v = values[i];
      27             :     DASH_LOG_TRACE("GlobStencilIterTest.print_region", name,
      28             :                    "region[", i, "] =", v);
      29             :   }
      30           6 : }
      31             : 
      32          20 : TEST_F(GlobStencilIterTest, Conversion)
      33             : {
      34             :   // Test conversion of GlobIter to GlobStencilIter:
      35             : 
      36             :   typedef double                         value_t;
      37             :   typedef dash::TilePattern<2>           pattern_t;
      38             :   typedef typename pattern_t::index_type index_t;
      39             :   typedef typename pattern_t::size_type  extent_t;
      40             : 
      41           4 :   auto     myid      = dash::myid();
      42           4 :   extent_t num_units = dash::size();
      43             : 
      44           4 :   if (num_units < 2) {
      45             :     LOG_MESSAGE("GlobStencilIterTest.Conversion requires at least 2 units");
      46           0 :     return;
      47             :   }
      48             : 
      49             :   // Default constructor creates team spec with extents (nunits, 1):
      50           4 :   dash::TeamSpec<2> teamspec;
      51             :   // Automatic balancing of team spec in two dimensions:
      52           4 :   teamspec.balance_extents();
      53             : 
      54           4 :   extent_t tilesize_rows   = 4;
      55           4 :   extent_t tilesize_cols   = 3;
      56           4 :   extent_t num_units_rows  = teamspec.extent(0);
      57           4 :   extent_t num_units_cols  = teamspec.extent(1);
      58           4 :   extent_t num_tiles_rows  = num_units_rows > 1 ? num_units_rows * 2 : 1;
      59           4 :   extent_t num_tiles_cols  = num_units_cols > 1 ? num_units_cols * 3 : 1;
      60           4 :   extent_t matrix_rows     = tilesize_rows * num_tiles_rows;
      61           4 :   extent_t matrix_cols     = tilesize_cols * num_tiles_cols;
      62           4 :   extent_t halo_rows       = tilesize_rows;
      63           4 :   extent_t halo_cols       = tilesize_cols;
      64           4 :   extent_t block_halo_size = 2 * halo_rows + 2 * (halo_cols - 2);
      65           4 :   extent_t stencil_points  = 5;
      66             : 
      67             :   pattern_t pattern(
      68             :     dash::SizeSpec<2>(
      69             :       matrix_rows,
      70             :       matrix_cols),
      71             :     dash::DistributionSpec<2>(
      72             :       num_units_rows < 2 ? dash::NONE : dash::TILE(tilesize_rows),
      73             :       num_units_cols < 2 ? dash::NONE : dash::TILE(tilesize_cols)),
      74           4 :     teamspec);
      75             : 
      76           8 :   dash::Matrix<value_t, 2, index_t, pattern_t> matrix(pattern);
      77             : 
      78             :   // Initialize values:
      79           4 :   auto n_local_blocks = pattern.local_blockspec().size();
      80          28 :   for (extent_t lbi = 0; lbi < n_local_blocks; ++lbi) {
      81             :     // submatrix view on local block obtained from matrix relative to global
      82             :     // memory space:
      83          24 :     auto g_matrix_block  = matrix.local.block(lbi);
      84             : 
      85          24 :     value_t * block_lbegin = g_matrix_block.lbegin();
      86          24 :     value_t * block_lend   = g_matrix_block.lend();
      87             :     DASH_LOG_DEBUG("MatrixTest.DelayedAlloc",
      88             :                    "local block idx:",   lbi,
      89             :                    "block offset:",      g_matrix_block.offsets(),
      90             :                    "block extents:",     g_matrix_block.extents(),
      91             :                    "block lend-lbegin:", block_lend - block_lbegin);
      92             :     // element phase, canonical element offset in block:
      93          24 :     index_t phase = 0;
      94         312 :     for (auto lbv = block_lbegin; lbv != block_lend; ++lbv, ++phase) {
      95         288 :       *lbv = myid + (0.01 * lbi) + (0.0001 * phase);
      96             :     }
      97             :   }
      98           4 :   matrix.barrier();
      99             : 
     100           4 :   if (myid == 0) {
     101           1 :     dash::test::print_matrix("Matrix<2>", matrix, 4);
     102           1 :     DASH_LOG_TRACE_VAR("GlobStencilIterTest.Conversion", teamspec.extents());
     103             : 
     104             :     std::array<index_t, 2> g_block_coords = {{
     105           1 :                              static_cast<index_t>(num_tiles_rows / 2),
     106           1 :                              static_cast<index_t>(num_tiles_cols / 2)
     107           2 :                            }};
     108             :     // Define halo for five-point stencil:
     109           1 :     dash::HaloSpec<2> halospec({{ { -1, 1 }, { -1, 1 } }});
     110           1 :     auto matrix_block   = matrix.block(g_block_coords);
     111             :     // Phase of element in the center of the block:
     112             :     auto b_center_idx   = dash::CartesianIndexSpace<2>(
     113           2 :                             matrix.pattern().block(g_block_coords).extents())
     114           3 :                           .at(tilesize_rows / 2,
     115           1 :                               tilesize_cols / 2);
     116           1 :     auto g_view_it      = matrix_block.begin() + b_center_idx;
     117           1 :     auto g_view_it_lpos = g_view_it.lpos();
     118             :     // Convert global view iterator to global stencil iterator:
     119             :     dash::GlobStencilIter<value_t, pattern_t> g_stencil_it(
     120             :                                                 g_view_it,
     121           1 :                                                 halospec);
     122             : 
     123           1 :     auto halo_view      = g_stencil_it.halo();
     124           1 :     ASSERT_EQ_U(stencil_points,   halo_view.npoints());
     125           1 :     ASSERT_EQ_U(stencil_points-1, halo_view.size());
     126             : 
     127           1 :     value_t north       = g_stencil_it.halo_cell({{ -1, 0 }});
     128           1 :     value_t east        = g_stencil_it.halo_cell({{  0, 1 }});
     129           1 :     value_t south       = g_stencil_it.halo_cell({{  1, 0 }});
     130           1 :     value_t west        = g_stencil_it.halo_cell({{  0,-1 }});
     131             : 
     132             :     LOG_MESSAGE("gvit = m.block(%d,%d).begin(), "
     133             :                 "gvit.pos:%d gvit.gpos:%d gvit.rpos:%d gvit.lpos:(u:%d li:%d) "
     134             :                 "value:%f halo(n:%f e:%f s:%f w:%f)",
     135             :                 g_block_coords[0],
     136             :                 g_block_coords[1],
     137             :                 g_view_it.pos(),
     138             :                 g_view_it.gpos(),
     139             :                 g_view_it.rpos(),
     140             :                 g_view_it_lpos.unit,
     141             :                 g_view_it_lpos.index,
     142             :                 static_cast<value_t>(*g_stencil_it),
     143             :                 north, east, south, west);
     144             :   }
     145             : }
     146             : 
     147          20 : TEST_F(GlobStencilIterTest, FivePoint2DimHaloBlock)
     148             : {
     149             :   typedef double                         value_t;
     150             :   typedef dash::TilePattern<2>           pattern_t;
     151             :   typedef typename pattern_t::index_type index_t;
     152             :   typedef typename pattern_t::size_type  extent_t;
     153             : 
     154           4 :   auto     myid      = dash::myid();
     155           4 :   extent_t num_units = dash::size();
     156             : 
     157           4 :   if (num_units < 4 || num_units % 2 != 0) {
     158             :     LOG_MESSAGE("GlobStencilIterTest.HaloBlock requires at least 4 units");
     159           0 :     return;
     160             :   }
     161             : 
     162             :   // Default constructor creates team spec with extents (nunits, 1):
     163           4 :   dash::TeamSpec<2> teamspec;
     164             :   // Automatic balancing of team spec in two dimensions:
     165           4 :   teamspec.balance_extents();
     166             : 
     167           4 :   extent_t tilesize_rows   = 4;
     168           4 :   extent_t tilesize_cols   = 3;
     169           4 :   extent_t num_units_rows  = teamspec.extent(0);
     170           4 :   extent_t num_units_cols  = teamspec.extent(1);
     171           4 :   extent_t num_tiles_rows  = num_units_rows > 1 ? num_units_rows * 2 : 1;
     172           4 :   extent_t num_tiles_cols  = num_units_cols > 1 ? num_units_cols * 3 : 1;
     173           4 :   extent_t matrix_rows     = tilesize_rows * num_tiles_rows;
     174           4 :   extent_t matrix_cols     = tilesize_cols * num_tiles_cols;
     175           4 :   extent_t halo_rows       = tilesize_rows;
     176           4 :   extent_t halo_cols       = tilesize_cols;
     177           4 :   extent_t block_halo_size = 2 * halo_rows + 2 * (halo_cols - 2);
     178           4 :   extent_t stencil_points  = 5;
     179             : 
     180             :   pattern_t pattern(
     181             :     dash::SizeSpec<2>(
     182             :       matrix_rows,
     183             :       matrix_cols),
     184             :     dash::DistributionSpec<2>(
     185             :       num_units_rows < 2 ? dash::NONE : dash::TILE(tilesize_rows),
     186             :       num_units_cols < 2 ? dash::NONE : dash::TILE(tilesize_cols)),
     187           4 :     teamspec);
     188             : 
     189           8 :   dash::Matrix<value_t, 2, index_t, pattern_t> matrix(pattern);
     190             : 
     191             :   // Initialize values:
     192           4 :   auto n_local_blocks = pattern.local_blockspec().size();
     193          28 :   for (extent_t lbi = 0; lbi < n_local_blocks; ++lbi) {
     194             :     // submatrix view on local block obtained from matrix relative to global
     195             :     // memory space:
     196          24 :     auto g_matrix_block    = matrix.local.block(lbi);
     197          24 :     value_t * block_lbegin = g_matrix_block.lbegin();
     198          24 :     value_t * block_lend   = g_matrix_block.lend();
     199             :     // element phase, canonical element offset in block:
     200          24 :     index_t phase = 0;
     201         312 :     for (auto lbv = block_lbegin; lbv != block_lend; ++lbv, ++phase) {
     202         288 :       *lbv = myid + (0.01 * lbi) + (0.0001 * phase);
     203             :     }
     204             :   }
     205           4 :   matrix.barrier();
     206             : 
     207           4 :   if (myid == 0) {
     208           1 :     dash::test::print_matrix("Matrix<2>", matrix, 4);
     209             :   }
     210             : 
     211           4 :   matrix.barrier();
     212             :   // clear matrix values:
     213           4 :   dash::fill(matrix.begin(), matrix.end(), 0.0);
     214             : 
     215           4 :   value_t halo_n_value = 1.1111;
     216           4 :   value_t halo_s_value = 2.2222;
     217           4 :   value_t halo_w_value = 3.3333;
     218           4 :   value_t halo_e_value = 4.4444;
     219           4 :   value_t bnd_n_value  = 0.1;
     220           4 :   value_t bnd_s_value  = 0.2;
     221           4 :   value_t bnd_w_value  = 0.3;
     222           4 :   value_t bnd_e_value  = 0.4;
     223             : 
     224           4 :   if (myid == 0) {
     225           1 :     DASH_LOG_TRACE_VAR("GlobStencilIterTest.HaloBlock", teamspec.extents());
     226           1 :     DASH_LOG_TRACE_VAR("GlobStencilIterTest.HaloBlock", pattern.extents());
     227           1 :     DASH_LOG_TRACE_VAR("GlobStencilIterTest.HaloBlock", pattern.blocksize(0));
     228           1 :     DASH_LOG_TRACE_VAR("GlobStencilIterTest.HaloBlock", pattern.blocksize(1));
     229           1 :     DASH_LOG_TRACE_VAR("GlobStencilIterTest.HaloBlock",
     230             :                        pattern.blockspec().extents());
     231             : 
     232             :     std::array<index_t, 2> g_block_coords = {{
     233           1 :                              static_cast<index_t>(num_tiles_rows / 2),
     234           1 :                              static_cast<index_t>(num_tiles_cols / 2)
     235           2 :                            }};
     236             :     // Define halo for five-point stencil:
     237           1 :     dash::HaloSpec<2> halospec({{ { -1, 1 }, { -1, 1 } }});
     238             : 
     239           1 :     ASSERT_EQ_U(1, halospec.width(0));
     240           1 :     ASSERT_EQ_U(1, halospec.width(1));
     241             : 
     242           1 :     auto matrix_block = matrix.block(g_block_coords);
     243           1 :     auto block_view   = matrix_block.viewspec();
     244             : 
     245             :     // write values in halo- and boundary cells only:
     246             :     DASH_LOG_TRACE("GlobStencilIterTest.HaloBlock",
     247             :                    "write to north and south boundary- and halo cells.",
     248             :                    "halospec rows:", halospec.width(0),
     249             :                    "block columns:", matrix_block.extent(1));
     250           2 :     for (int hi = 0; hi < halospec.width(0); ++hi) {
     251           4 :       for (int hj = 0; hj < matrix_block.extent(1); ++hj) {
     252             :         DASH_LOG_TRACE("GlobStencilIterTest.HaloBlock",
     253             :                        "( hi:", hi, "hj:", hj, ")");
     254             :         // write values into north halo:
     255           3 :         auto nhi = block_view.offset(0) - halospec.width(0) + hi;
     256           3 :         auto nhj = block_view.offset(1) + hj;
     257           3 :         matrix[nhi][nhj] = halo_n_value;
     258             :         // write values into south halo:
     259           3 :         auto shi = block_view.offset(0) + block_view.extent(0) + hi;
     260           3 :         auto shj = block_view.offset(1) + hj;
     261           3 :         matrix[shi][shj] = halo_s_value;
     262             :         // write values into north boundary:
     263           3 :         auto nbi = block_view.offset(0) + hi;
     264           3 :         auto nbj = block_view.offset(1) + hj;
     265           3 :         matrix[nbi][nbj] = bnd_n_value;
     266             :         // write values into south boundary:
     267           6 :         auto sbi = block_view.offset(0) + block_view.extent(0) -
     268           6 :                    halospec.width(0) + hi;
     269           3 :         auto sbj = block_view.offset(1) + hj;
     270           3 :         matrix[sbi][sbj] = bnd_s_value;
     271             :       }
     272             :     }
     273             :     DASH_LOG_TRACE("GlobStencilIterTest.HaloBlock",
     274             :                    "write to west and east boundary- and halo cells.",
     275             :                    "block rows:",       matrix_block.extent(0),
     276             :                    "halospec columns:", halospec.width(1));
     277           5 :     for (int hi = 0; hi < matrix_block.extent(0); ++hi) {
     278           8 :       for (int hj = 0; hj < halospec.width(1); ++hj) {
     279             :         DASH_LOG_TRACE("GlobStencilIterTest.HaloBlock",
     280             :                        "( hi:", hi, "hj:", hj, ")");
     281             :         // write values into west halo:
     282           4 :         auto whi = block_view.offset(0) + hi;
     283           4 :         auto whj = block_view.offset(1) - halospec.width(1) + hj;
     284           4 :         matrix[whi][whj] = halo_w_value;
     285             :         // write values into east halo:
     286           4 :         auto ehi = block_view.offset(0) + hi;
     287           4 :         auto ehj = block_view.offset(1) + block_view.extent(1) + hj;
     288           4 :         matrix[ehi][ehj] = halo_e_value;
     289             :         // write values into west boundary:
     290           8 :         auto bi_max = block_view.offset(0) + block_view.extent(0) -
     291           8 :                       halospec.width(0);
     292           4 :         auto wbi = block_view.offset(0) + hi + halospec.width(0);
     293           4 :         auto wbj = block_view.offset(1) + hj;
     294           4 :         if (wbi < bi_max) {
     295           2 :           matrix[wbi][wbj] = bnd_w_value;
     296             :         }
     297             :         // write values into east boundary:
     298           4 :         auto ebi = block_view.offset(0) + hi + halospec.width(0);
     299           8 :         auto ebj = block_view.offset(1) + block_view.extent(1) -
     300           8 :                    halospec.width(1)+ hj;
     301           4 :         if (ebi < bi_max) {
     302           2 :           matrix[ebi][ebj] = bnd_e_value;
     303             :         }
     304             :       }
     305             :     }
     306           1 :     dash::test::print_matrix("Matrix<2>", matrix, 2);
     307             : 
     308             :     dash::HaloBlock<value_t, pattern_t> halo_block(
     309           2 :                                           &matrix.begin().globmem(),
     310             :                                           pattern,
     311             :                                           block_view,
     312           2 :                                           halospec);
     313           2 :     auto block_boundary   = halo_block.boundary();
     314           2 :     auto block_bnd_begin  = block_boundary.begin();
     315           2 :     auto block_bnd_end    = block_boundary.end();
     316           2 :     auto block_halo       = halo_block.halo();
     317           2 :     auto block_halo_begin = block_halo.begin();
     318           2 :     auto block_halo_end   = block_halo.end();
     319             :     // inner cells in boundary:
     320           1 :     auto exp_bnd_size     = (tilesize_rows * 2) + ((tilesize_cols-2) * 2);
     321             :     // outer cells in halo:
     322           1 :     auto exp_halo_size    = (tilesize_rows * 2) + (tilesize_cols * 2);
     323             : 
     324             :     std::array<index_t, 2>  inner_block_offsets = {{
     325           1 :         block_view.offset(0) + halospec.offset_range(0).min,
     326           1 :         block_view.offset(1) + halospec.offset_range(1).min
     327           2 :     }};
     328             :     std::array<extent_t, 2> inner_block_extents = {{
     329           1 :         block_view.extent(0) + halospec.width(0) * 2,
     330           1 :         block_view.extent(1) + halospec.width(1) * 2
     331           2 :     }};
     332           1 :     dash::ViewSpec<2> exp_inner_view(block_view);
     333             :     dash::ViewSpec<2> exp_outer_view(inner_block_offsets,
     334           1 :                                      inner_block_extents);
     335             : 
     336             :     DASH_LOG_TRACE("GlobStencilIterTest.HaloBlock", "original block:",
     337             :                    "size:",          block_view.size(),
     338             :                    "offsets:",       block_view.offsets(),
     339             :                    "extents:",       block_view.extents());
     340             :     DASH_LOG_TRACE("GlobStencilIterTest.HaloBlock", "inner block view:",
     341             :                    "boundary size:", block_boundary.size(),
     342             :                    "offsets:",       halo_block.inner().offsets(),
     343             :                    "extents:",       halo_block.inner().extents());
     344             :     DASH_LOG_TRACE("GlobStencilIterTest.HaloBlock", "outer block view:",
     345             :                    "halo size:",     block_halo.size(),
     346             :                    "offsets:",       halo_block.outer().offsets(),
     347             :                    "extents:",       halo_block.outer().extents());
     348             : 
     349           1 :     ASSERT_EQ_U(exp_bnd_size,   block_boundary.size());
     350           1 :     ASSERT_EQ_U(exp_bnd_size,   block_bnd_end - block_bnd_begin);
     351           1 :     ASSERT_EQ_U(exp_halo_size,  block_halo.size());
     352           1 :     ASSERT_EQ_U(exp_halo_size,  block_halo_end - block_halo_begin);
     353           1 :     ASSERT_EQ_U(exp_inner_view, halo_block.inner());
     354           1 :     ASSERT_EQ_U(exp_outer_view, halo_block.outer());
     355             : 
     356           1 :     print_region<value_t>("block_halo", block_halo_begin, block_halo_end);
     357           1 :     print_region<value_t>("block_halo", block_bnd_begin,  block_bnd_end);
     358             : 
     359             :     // create local copy of halo regions and validate values:
     360             : 
     361           2 :     auto h_region_n = halo_block.halo_region({ -1,  0 });
     362           2 :     auto h_region_s = halo_block.halo_region({  1,  0 });
     363           2 :     auto h_region_w = halo_block.halo_region({  0, -1 });
     364           2 :     auto h_region_e = halo_block.halo_region({  0,  1 });
     365             : 
     366           2 :     print_region<value_t>("halo_n_region",
     367           3 :                           h_region_n.begin(), h_region_n.end());
     368           2 :     print_region<value_t>("halo_s_region",
     369           3 :                           h_region_s.begin(), h_region_s.end());
     370           2 :     print_region<value_t>("halo_w_region",
     371           3 :                           h_region_w.begin(), h_region_w.end());
     372           2 :     print_region<value_t>("halo_e_region",
     373           3 :                           h_region_e.begin(), h_region_e.end());
     374             : 
     375             :     // validate values in halo cells:
     376             : 
     377             :     // TODO: Yields incorrect failures for uneven tiles:
     378             : #if 0
     379             :     ASSERT_EQ_U(std::count(
     380             :                   h_region_n.begin(), h_region_n.end(), halo_n_value),
     381             :                 tilesize_cols);
     382             :     ASSERT_EQ_U(std::count(
     383             :                   h_region_s.begin(), h_region_s.end(), halo_s_value),
     384             :                 tilesize_cols);
     385             :     ASSERT_EQ_U(std::count(
     386             :                   h_region_w.begin(), h_region_w.end(), halo_w_value),
     387             :                 tilesize_rows);
     388             :     ASSERT_EQ_U(std::count(
     389             :                   h_region_e.begin(), h_region_e.end(), halo_e_value),
     390             :                 tilesize_rows);
     391             : #endif
     392             :   }
     393          12 : }
     394             : 

Generated by: LCOV version 1.12