LCOV - code coverage report
Current view: top level - test - CopyTest.cc (source / functions) Hit Total Coverage
Test: coverage.info.cleaned Lines: 342 348 98.3 %
Date: 2016-06-29 12:30:40 Functions: 48 48 100.0 %

          Line data    Source code
       1             : 
       2             : #include <libdash.h>
       3             : #include <gtest/gtest.h>
       4             : 
       5             : #include "TestBase.h"
       6             : #include "TestLogHelpers.h"
       7             : #include "CopyTest.h"
       8             : 
       9          20 : TEST_F(CopyTest, BlockingGlobalToLocalBlock)
      10             : {
      11             :   // Copy all elements contained in a single, continuous block.
      12           4 :   const int num_elem_per_unit = 20;
      13           4 :   size_t num_elem_total       = _dash_size * num_elem_per_unit;
      14             : 
      15           8 :   dash::Array<int> array(num_elem_total, dash::BLOCKED);
      16             : 
      17             :   // Assign initial values: [ 1000, 1001, 1002, ... 2000, 2001, ... ]
      18          84 :   for (auto l = 0; l < num_elem_per_unit; ++l) {
      19          80 :     array.local[l] = ((dash::myid() + 1) * 1000) + l;
      20             :   }
      21           4 :   array.barrier();
      22             : 
      23             :   // Local range to store copy:
      24           4 :   int * local_copy = new int[num_elem_per_unit];
      25             : 
      26             :   // Copy values from global range to local memory.
      27             :   // All units copy first block, so unit 0 tests local-to-local copying.
      28           4 :   int * dest_end = dash::copy(array.begin(),
      29           8 :                               array.begin() + num_elem_per_unit,
      30           4 :                               local_copy);
      31           4 :   ASSERT_EQ_U(local_copy + num_elem_per_unit, dest_end);
      32          84 :   for (auto l = 0; l < num_elem_per_unit; ++l) {
      33          80 :     ASSERT_EQ_U(static_cast<int>(array[l]),
      34             :                 local_copy[l]);
      35             :   }
      36           4 :   delete[] local_copy;
      37             : }
      38             : 
      39          20 : TEST_F(CopyTest, Blocking2DimGlobalToLocalBlock)
      40             : {
      41             :   // Copy all blocks from a single remote unit.
      42           4 :   const size_t block_size_x  = 3;
      43           4 :   const size_t block_size_y  = 2;
      44           4 :   const size_t block_size    = block_size_x * block_size_y;
      45           4 :   size_t num_local_blocks_x  = 2;
      46           4 :   size_t num_local_blocks_y  = 2;
      47           4 :   size_t num_blocks_x        = _dash_size * num_local_blocks_x;
      48           4 :   size_t num_blocks_y        = _dash_size * num_local_blocks_y;
      49           4 :   size_t num_blocks_total    = num_blocks_x * num_blocks_y;
      50           4 :   size_t extent_x            = block_size_x * num_blocks_x;
      51           4 :   size_t extent_y            = block_size_y * num_blocks_y;
      52           4 :   size_t num_elem_total      = extent_x * extent_y;
      53             :   // Assuming balanced mapping:
      54           4 :   size_t num_elem_per_unit   = num_elem_total / _dash_size;
      55           4 :   size_t num_blocks_per_unit = num_elem_per_unit / block_size;
      56             : 
      57           4 :   if (_dash_size < 2) {
      58             :     LOG_MESSAGE("CopyTest.Blocking2DimGlobalToLocalBlock "
      59             :                 "requires > 1 units");
      60           0 :     return;
      61             :   }
      62             : 
      63             :   LOG_MESSAGE("nunits:%d elem_total:%d "
      64             :               "elem_per_unit:%d blocks_per_unit:%d",
      65             :               _dash_size, num_elem_total,
      66             :               num_elem_per_unit, num_blocks_per_unit);
      67             : 
      68             :   typedef dash::ShiftTilePattern<2>      pattern_t;
      69             :   typedef typename pattern_t::index_type index_t;
      70             :   typedef float                          value_t;
      71             : 
      72             :   pattern_t pattern(
      73             :     dash::SizeSpec<2>(
      74             :       extent_x,
      75             :       extent_y),
      76             :     dash::DistributionSpec<2>(
      77           8 :       dash::TILE(block_size_x),
      78           8 :       dash::TILE(block_size_y))
      79           4 :   );
      80             : 
      81             :   dash::Matrix<value_t, 2, dash::default_index_t, pattern_t>
      82           8 :     matrix(pattern);
      83             : 
      84             :   // Assign initial values:
      85          68 :   for (size_t lb = 0; lb < num_blocks_per_unit; ++lb) {
      86             :     LOG_MESSAGE("initialize values in local block %d", lb);
      87          64 :     auto lblock         = matrix.local.block(lb);
      88          64 :     auto lblock_view    = lblock.begin().viewspec();
      89          64 :     auto lblock_extents = lblock_view.extents();
      90          64 :     auto lblock_offsets = lblock_view.offsets();
      91             :     dash__unused(lblock_offsets);
      92          64 :     ASSERT_EQ_U(block_size_x, lblock_extents[0]);
      93          64 :     ASSERT_EQ_U(block_size_y, lblock_extents[1]);
      94             :     LOG_MESSAGE("local block %d offset: (%d,%d) extent: (%d,%d)",
      95             :                 lb,
      96             :                 lblock_offsets[0], lblock_offsets[1],
      97             :                 lblock_extents[0], lblock_extents[1]);
      98         256 :     for (auto bx = 0; bx < static_cast<int>(lblock_extents[0]); ++bx) {
      99         576 :       for (auto by = 0; by < static_cast<int>(lblock_extents[1]); ++by) {
     100             :         // Phase coordinates (bx,by) to global coordinates (gx,gy):
     101         384 :         index_t gx       = lblock_view.offset(0) + bx;
     102         384 :         index_t gy       = lblock_view.offset(1) + by;
     103             :         dash__unused(gx);
     104             :         dash__unused(gy);
     105         768 :         value_t value    = static_cast<value_t>(dash::myid() + 1) +
     106         384 :                            (0.00001 * (
     107         768 :                              ((lb + 1) * 10000) +
     108         768 :                              ((bx + 1) * 100) +
     109         384 :                              by + 1
     110         384 :                            ));
     111             :         LOG_MESSAGE("set local block %d at phase:(%d,%d) g:(%d,%d) = %f",
     112             :                     lb, bx, by, gx, gy, value);
     113         384 :         lblock[bx][by] = value;
     114             :       }
     115             :     }
     116             :   }
     117             : 
     118           4 :   matrix.barrier();
     119             : 
     120             :   // Log matrix values:
     121           4 :   if (dash::myid() == 0) {
     122           2 :     std::vector< std::vector<value_t> > matrix_values;
     123          25 :     for (size_t x = 0; x < extent_x; ++x) {
     124          48 :       std::vector<value_t> row;
     125         408 :       for (size_t y = 0; y < extent_y; ++y) {
     126             :         DASH_LOG_DEBUG("CopyTest.Blocking2Dim", "get matrix value at",
     127             :                        "x:", x,
     128             :                        "y:", y);
     129         384 :         value_t value = matrix[x][y];
     130         384 :         row.push_back(value);
     131             :       }
     132          24 :       matrix_values.push_back(row);
     133             :     }
     134          25 :     for (size_t row = 0; row < extent_x; ++row) {
     135          24 :       DASH_LOG_DEBUG_VAR("CopyTest.Blocking2Dim", matrix_values[row]);
     136             :     }
     137             :   }
     138             : 
     139           4 :   matrix.barrier();
     140             : 
     141             :   // Array to store local copy:
     142           4 :   value_t * local_copy = new value_t[num_elem_per_unit];
     143             :   // Pointer to first value in next copy destination range:
     144           4 :   value_t * copy_dest_begin = local_copy;
     145           4 :   value_t * copy_dest_last  = local_copy;
     146             : 
     147             :   //
     148             :   // Create local copy of all blocks from a single remote unit:
     149             :   //
     150           4 :   dart_unit_t remote_unit_id = (dash::myid() + 1) % _dash_size;
     151             :   LOG_MESSAGE("Creating local copy of blocks at remote unit %d",
     152             :               remote_unit_id);
     153           4 :   int rb = 0;
     154         260 :   for (size_t gb = 0; gb < num_blocks_total; ++gb) {
     155             :     // View of block at global block index gb:
     156         256 :     auto g_block_view = pattern.block(gb);
     157             :     // Unit assigned to block at global block index gb:
     158         512 :     auto g_block_unit = pattern.unit_at(
     159             :                           std::array<index_t, 2> {0,0},
     160         256 :                           g_block_view);
     161             :     LOG_MESSAGE("Block %d: assigned to unit %d", gb, g_block_unit);
     162         256 :     if (g_block_unit == remote_unit_id) {
     163             :       // Block is assigned to selecte remote unit, create local copy:
     164             :       LOG_MESSAGE("Creating local copy of block %d", gb);
     165          64 :       auto remote_block      = matrix.block(gb);
     166          64 :       auto remote_block_view = remote_block.begin().viewspec();
     167             :       dash__unused(remote_block_view);
     168             :       LOG_MESSAGE("Block %d index range: (%d..%d] "
     169             :                   "offset: (%d,%d) extent: (%d,%d)",
     170             :                   gb, remote_block.begin().pos(), remote_block.end().pos(),
     171             :                   remote_block_view.offset(0), remote_block_view.offset(1),
     172             :                   remote_block_view.extent(0), remote_block_view.extent(1));
     173          64 :       copy_dest_last = dash::copy(remote_block.begin(),
     174             :                                   remote_block.end(),
     175          64 :                                   copy_dest_begin);
     176             :       // Validate number of copied elements:
     177          64 :       auto num_copied = copy_dest_last - copy_dest_begin;
     178          64 :       ASSERT_EQ_U(num_copied, block_size);
     179             :       // Advance local copy destination pointer:
     180          64 :       copy_dest_begin = copy_dest_last;
     181          64 :       ++rb;
     182             :     }
     183             :   }
     184             :   // Validate number of copied blocks:
     185           4 :   ASSERT_EQ_U(num_blocks_per_unit, rb);
     186             : 
     187             :   // Log values in local copy:
     188           8 :   std::vector< std::vector<value_t> > local_block_values;
     189          68 :   for (size_t lb = 0; lb < num_blocks_per_unit; ++lb) {
     190         256 :     for (size_t bx = 0; bx < block_size_x; ++bx) {
     191         384 :       std::vector<value_t> row;
     192         576 :       for (size_t by = 0; by < block_size_y; ++by) {
     193         384 :         auto l_offset = (lb * block_size) + (bx * block_size_y) + by;
     194         384 :         auto value    = local_copy[l_offset];
     195         384 :         row.push_back(value);
     196             :       }
     197         192 :       local_block_values.push_back(row);
     198             :     }
     199             :   }
     200           4 :   for (auto row : local_block_values) {
     201             :     DASH_LOG_DEBUG_VAR("CopyTest.Blocking2Dim", row);
     202             :   }
     203             : 
     204             :   // Validate values:
     205          68 :   for (size_t lb = 0; lb < num_blocks_per_unit; ++lb) {
     206         256 :     for (size_t bx = 0; bx < block_size_x; ++bx) {
     207         576 :       for (size_t by = 0; by < block_size_y; ++by) {
     208         384 :         auto    l_offset = (lb * block_size) + (bx * block_size_y) + by;
     209         768 :         value_t expected = static_cast<value_t>(remote_unit_id + 1) +
     210         384 :                            (0.00001 * (
     211         768 :                              ((lb + 1) * 10000) +
     212         768 :                              ((bx + 1) * 100) +
     213         384 :                              by + 1
     214         384 :                            ));
     215             :         LOG_MESSAGE("Validating block %d at block coords (%d,%d), "
     216             :                     "local offset: %d = %f",
     217             :                     lb, bx, by, l_offset, expected);
     218         384 :         ASSERT_EQ_U(expected, local_copy[l_offset]);
     219             :       }
     220             :     }
     221             :   }
     222           4 :   delete[] local_copy;
     223             : 
     224             :   //
     225             :   // Create local copy of first local block (local to local):
     226             :   //
     227             :   value_t local_block_copy[block_size];
     228           4 :   int  lb      = 0;
     229           4 :   auto l_block = matrix.local.block(lb);
     230             :   LOG_MESSAGE("Creating local copy of first local block");
     231             :   value_t * local_block_copy_last =
     232           4 :     dash::copy(l_block.begin(),
     233             :                l_block.end(),
     234           4 :                local_block_copy);
     235             :   // Validate number of copied elements:
     236           4 :   auto num_copied = local_block_copy_last - local_block_copy;
     237           4 :   ASSERT_EQ_U(num_copied, block_size);
     238          16 :   for (size_t bx = 0; bx < block_size_x; ++bx) {
     239          36 :     for (size_t by = 0; by < block_size_y; ++by) {
     240          24 :       auto    l_offset = (bx * block_size_y) + by;
     241          48 :       value_t expected = static_cast<value_t>(dash::myid() + 1) +
     242          24 :                          (0.00001 * (
     243          48 :                            ((lb + 1) * 10000) +
     244          48 :                            ((bx + 1) * 100) +
     245          24 :                            by + 1
     246          24 :                          ));
     247          24 :       ASSERT_EQ_U(expected, local_block_copy[l_offset]);
     248             :     }
     249             :   }
     250             : }
     251             : 
     252          20 : TEST_F(CopyTest, BlockingGlobalToLocalMasterOnlyAllRemote)
     253             : {
     254             :   typedef int64_t index_t;
     255             :   typedef dash::Array<
     256             :             int,
     257             :             index_t,
     258             :             dash::CSRPattern<1, dash::ROW_MAJOR, index_t>
     259             :           > Array_t;
     260           4 :   if (_dash_size < 2) {
     261           0 :     return;
     262             :   }
     263             :   // Copy all elements contained in a single, continuous block.
     264           4 :   const int num_elem_per_unit = 250;
     265           4 :   size_t    num_elem_total    = _dash_size * num_elem_per_unit;
     266           4 :   size_t    num_copy_elem     = (_dash_size - 1) * num_elem_per_unit;
     267             : 
     268           8 :   Array_t   array(num_elem_total, dash::BLOCKED);
     269           4 :   auto      l_start_idx       = array.pattern().lbegin();
     270           4 :   auto      l_end_idx         = array.pattern().lend();
     271             : 
     272             :   LOG_MESSAGE("lstart:%d lend:%d ncopy:%d",
     273             :               l_start_idx, l_end_idx, num_copy_elem);
     274             : 
     275             :   // Assign initial values: [ 1000, 1001, 1002, ... 2000, 2001, ... ]
     276        1004 :   for (int l = 0; l < num_elem_per_unit; ++l) {
     277        1000 :     array.local[l] = ((dash::myid() + 1) * 1000) + l;
     278             :   }
     279           4 :   array.barrier();
     280             : 
     281             :   // Local range to store copy:
     282           4 :   int * local_copy = new int[num_copy_elem];
     283           4 :   int * dest_first = local_copy;
     284           4 :   int * dest_last  = local_copy;
     285           4 :   if (dash::myid() == 0) {
     286             :     // Copy elements in front of local range:
     287             :     LOG_MESSAGE("Copying from global range (%d-%d]",
     288             :                 0, l_start_idx);
     289           1 :     dest_first = dash::copy(
     290             :                    array.begin(),
     291           2 :                    array.begin() + l_start_idx,
     292           1 :                    dest_first);
     293             :     // Copy elements after local range:
     294             :     LOG_MESSAGE("Copying from global range (%d-%d]",
     295             :                 l_end_idx, array.size());
     296           2 :     dest_last  = dash::copy(
     297           2 :                    array.begin() + l_end_idx,
     298             :                    array.end(),
     299           1 :                    dest_first);
     300             :     dash__unused(dest_last);
     301             :     LOG_MESSAGE("Validating elements");
     302           1 :     int l = 0;
     303        1001 :     for (size_t g = 0; g < array.size(); ++g) {
     304        1000 :       if (array.pattern().unit_at(g) != dash::myid()) {
     305         750 :         int expected = array[g];
     306             :         LOG_MESSAGE("Validating value at global index %d (local: %d) = %d",
     307             :                     g, l, expected);
     308         750 :         ASSERT_EQ_U(expected, local_copy[l]);
     309         750 :         ++l;
     310             :       }
     311             :     }
     312             :   }
     313           4 :   delete[] local_copy;
     314             : }
     315             : 
     316          20 : TEST_F(CopyTest, BlockingGlobalToLocalBarrierUnaligned)
     317             : {
     318           4 :   dart_unit_t myid       = dash::myid();
     319           4 :   size_t num_units       = dash::Team::All().size();
     320           4 :   size_t num_elems_unit  = 20;
     321           4 :   size_t start_index     = 7;
     322           4 :   size_t num_elems_copy  = 20;
     323           4 :   size_t num_elems_total = num_elems_unit * num_units;
     324             : 
     325           4 :   int *  local_array = new int[num_elems_copy];
     326           8 :   dash::Array<int> array(num_elems_total);
     327             : 
     328             :   LOG_MESSAGE("Elements per unit: %d", num_elems_unit);
     329             :   LOG_MESSAGE("Start index:       %d", start_index);
     330             :   LOG_MESSAGE("Elements to copy:  %d", num_elems_copy);
     331             :   LOG_MESSAGE("Array size:        %d", array.size());
     332             : 
     333           4 :   std::fill(array.lbegin(), array.lend(), myid);
     334             : 
     335           4 :   array.barrier();
     336             : 
     337          12 :   dash::copy(array.begin() + start_index,
     338           8 :              array.begin() + start_index + num_elems_copy,
     339           4 :              local_array);
     340             : 
     341           4 :   for(size_t i = 0; i < num_elems_copy; ++i) {
     342             :     LOG_MESSAGE("Testing local element %lu = %d", i, local_array[i]);
     343             :   }
     344             : 
     345           4 :   array.barrier();
     346             : 
     347          84 :   for (size_t l = 0; l < num_elems_unit; ++l) {
     348          80 :     ASSERT_EQ_U(local_array[l],
     349             :                 static_cast<int>(array[start_index + l]));
     350             :   }
     351           4 :   delete[] local_array;
     352             : }
     353             : 
     354          20 : TEST_F(CopyTest, BlockingLocalToGlobalBlock)
     355             : {
     356             :   // Copy all elements contained in a single, continuous block.
     357           4 :   const int num_elem_per_unit = 20;
     358           4 :   size_t num_elem_total       = _dash_size * num_elem_per_unit;
     359             : 
     360             :   // Global target range:
     361           8 :   dash::Array<int> array(num_elem_total, dash::BLOCKED);
     362             :   // Local range to copy:
     363             :   int local_range[num_elem_per_unit];
     364             : 
     365             :   // Assign initial values: [ 1000, 1001, 1002, ... 2000, 2001, ... ]
     366          84 :   for (auto l = 0; l < num_elem_per_unit; ++l) {
     367          80 :     array.local[l] = 0;
     368          80 :     local_range[l] = ((dash::myid() + 1) * 1000) + l;
     369             :   }
     370           4 :   array.barrier();
     371             : 
     372             :   // Copy values from local range to remote global range.
     373             :   // All units (u) copy into block (nblocks-1-u), so unit 0 copies into
     374             :   // last block.
     375           4 :   auto block_offset  = _dash_size - 1 - dash::myid();
     376           4 :   auto global_offset = block_offset * num_elem_per_unit;
     377             :   dash::copy(local_range,
     378             :              local_range + num_elem_per_unit,
     379           4 :              array.begin() + global_offset);
     380             : 
     381           4 :   array.barrier();
     382             : 
     383          84 :   for (auto l = 0; l < num_elem_per_unit; ++l) {
     384          80 :     ASSERT_EQ_U(local_range[l],
     385             :                 static_cast<int>(array[global_offset + l]));
     386             :   }
     387             : }
     388             : 
     389          20 : TEST_F(CopyTest, BlockingGlobalToLocalSubBlock)
     390             : {
     391             :   // Copy all elements contained in a single, continuous block,
     392             :   // starting from an index unequal 0.
     393           4 :   const size_t num_elems_per_unit = 20;
     394           4 :   const size_t num_elems_total    = _dash_size * num_elems_per_unit;
     395             :   // Number of elements to copy
     396           4 :   const size_t num_elems_copy     = 5;
     397             :   // Index to start the copy
     398           4 :   const size_t start_index        = 5;
     399             : 
     400           8 :   dash::Array<int> array(num_elems_total, dash::BLOCKED);
     401             : 
     402             :   // Assign initial values: [ 1000, 1001, 1002, ... 2000, 2001, ... ]
     403          84 :   for (size_t l = 0; l < num_elems_per_unit; ++l) {
     404          80 :     array.local[l] = ((dash::myid() + 1) * 1000) + l;
     405             :   }
     406             :   LOG_MESSAGE("Waiting for barrier");
     407           4 :   array.barrier();
     408             : 
     409             :   // Local range to store copy:
     410             :   int local_array[num_elems_copy];
     411             : 
     412             :   // Copy values from global range to local memory.
     413             :   // All units copy a part of the first block, so unit 0 tests
     414             :   // local-to-local copying.
     415           8 :   dash::copy(array.begin() + start_index,
     416           8 :              array.begin() + start_index + num_elems_copy,
     417           4 :              local_array);
     418             : 
     419             :   LOG_MESSAGE("Waiting for barrier");
     420           4 :   array.barrier();
     421             : 
     422          24 :   for (size_t l = 0; l < num_elems_copy; ++l) {
     423             :     LOG_MESSAGE("Testing local value %d", l);
     424          20 :     ASSERT_EQ_U(static_cast<int>(array[l+start_index]), local_array[l]);
     425             :   }
     426             : }
     427             : 
     428          20 : TEST_F(CopyTest, BlockingGlobalToLocalSubBlockTwoUnits)
     429             : {
     430             :   // Copy all elements contained in a single, continuous block,
     431             :   // starting from an index unequal 0.
     432             : 
     433           4 :   if(_dash_size < 2)
     434           0 :     return;
     435             : 
     436           4 :   const size_t num_elems_per_unit = 20;
     437           4 :   const size_t num_elems_total    = _dash_size * num_elems_per_unit;
     438             :   // Number of elements to copy
     439           4 :   const size_t num_elems_copy     = num_elems_per_unit;
     440             :   // Index to start the copy
     441           4 :   const size_t start_index        = 5;
     442             : 
     443           8 :   dash::Array<int> array(num_elems_total, dash::BLOCKED);
     444             : 
     445             :   // Assign initial values: [ 1000, 1001, 1002, ... 2000, 2001, ... ]
     446          84 :   for (size_t l = 0; l < num_elems_per_unit; ++l) {
     447          80 :     array.local[l] = ((dash::myid() + 1) * 1000) + l;
     448             :   }
     449           4 :   array.barrier();
     450             : 
     451             :   // Local range to store copy:
     452             :   int local_array[num_elems_copy];
     453             : 
     454             :   // Copy values from global range to local memory.
     455             :   // All units copy a part of the first block, so unit 0 tests
     456             :   // local-to-local copying.
     457           8 :   dash::copy(array.begin() + start_index,
     458           8 :              array.begin() + start_index + num_elems_copy,
     459           4 :              local_array);
     460           4 :   for (size_t l = 0; l < num_elems_copy; ++l) {
     461             :     LOG_MESSAGE("Testing local element %d = %d", l, local_array[l]);
     462             :   }
     463          84 :   for (size_t l = 0; l < num_elems_copy; ++l) {
     464          80 :     ASSERT_EQ_U(static_cast<int>(array[l+start_index]), local_array[l]);
     465             :   }
     466             : }
     467             : 
     468          20 : TEST_F(CopyTest, BlockingGlobalToLocalSubBlockThreeUnits)
     469             : {
     470             :   // Copy all elements contained in a single, continuous block,
     471             :   // starting from an index unequal 0.
     472             : 
     473           4 :   if(_dash_size < 3) {
     474             :     LOG_MESSAGE("CopyTest.BlockingGlobalToLocalSubBlockThreeUnits "
     475             :                 "requires > 3 units");
     476           0 :     return;
     477             :   }
     478             : 
     479           4 :   const size_t num_elems_per_unit = 20;
     480           4 :   const size_t num_elems_total    = _dash_size * num_elems_per_unit;
     481             :   // Number of elements to copy
     482           4 :   const size_t num_elems_copy     = num_elems_per_unit * 2;
     483             :   // Index to start the copy
     484           4 :   const size_t start_index        = 5;
     485             : 
     486           8 :   dash::Array<int> array(num_elems_total, dash::BLOCKED);
     487             : 
     488             :   // Assign initial values: [ 1000, 1001, 1002, ... 2000, 2001, ... ]
     489          84 :   for (size_t l = 0; l < num_elems_per_unit; ++l) {
     490          80 :     array.local[l] = ((dash::myid() + 1) * 1000) + l;
     491             :   }
     492           4 :   array.barrier();
     493             : 
     494             :   // Local range to store copy:
     495           4 :   int * local_array = new int[num_elems_copy];
     496             : 
     497             :   // Copy values from global range to local memory.
     498             :   // All units copy a part of the first block, so unit 0 tests
     499             :   // local-to-local copying.
     500           8 :   dash::copy(array.begin() + start_index,
     501           8 :              array.begin() + start_index + num_elems_copy,
     502           4 :              local_array);
     503           4 :   for (size_t l = 0; l < num_elems_copy; ++l) {
     504             :     LOG_MESSAGE("Testing local element %d = %d", l, local_array[l]);
     505             :   }
     506         164 :   for (size_t l = 0; l < num_elems_copy; ++l) {
     507         160 :     ASSERT_EQ_U(static_cast<int>(array[l+start_index]), local_array[l]);
     508             :   }
     509           4 :   delete[] local_array;
     510             : }
     511             : 
     512          20 : TEST_F(CopyTest, AsyncGlobalToLocalTiles)
     513             : {
     514             :   typedef double
     515             :     value_t;
     516             :   typedef dash::TilePattern<2>
     517             :     pattern_t;
     518             :   typedef dash::Matrix<value_t, 2, dash::default_index_t, pattern_t>
     519             :     matrix_t;
     520             :   typedef typename pattern_t::index_type
     521             :     index_t;
     522             : 
     523           4 :   if (_dash_size < 3) {
     524             :     LOG_MESSAGE("CopyTest.AsyncGlobalToLocalTiles requires > 3 units");
     525           0 :     return;
     526             :   }
     527           4 :   if (_dash_size % 2 != 0) {
     528             :     LOG_MESSAGE("Team size must be multiple of 2 for "
     529             :                 "CopyTest.AsyncGlobalToLocalTiles");
     530           0 :     return;
     531             :   }
     532             : 
     533           4 :   size_t tilesize_x     = 2;
     534           4 :   size_t tilesize_y     = 3;
     535           4 :   size_t num_block_elem = tilesize_x * tilesize_y;
     536             :   // Additional blocks in both dimensions to ensure unbalanced mapping:
     537           4 :   size_t odd_blocks_x   = std::ceil(sqrt(_dash_size)) + 1;
     538           4 :   size_t odd_blocks_y   = 1;
     539           4 :   size_t num_blocks_x   = (_dash_size / 2 + odd_blocks_x);
     540           4 :   size_t num_blocks_y   = (_dash_size / 2 + odd_blocks_y);
     541           4 :   size_t extent_x       = num_blocks_x * tilesize_x;
     542           4 :   size_t extent_y       = num_blocks_y * tilesize_y;
     543             : 
     544           4 :   dash::SizeSpec<2> sizespec(extent_x, extent_y);
     545           8 :   dash::DistributionSpec<2> distspec(dash::TILE(tilesize_x),
     546          12 :                                      dash::TILE(tilesize_y));
     547           4 :   dash::TeamSpec<2> teamspec;
     548           4 :   teamspec.balance_extents();
     549             : 
     550             :   LOG_MESSAGE("SizeSpec(%lu,%lu) TeamSpec(%lu,%lu)",
     551             :               sizespec.extent(0), sizespec.extent(1),
     552             :               teamspec.extent(0), teamspec.extent(1));
     553             : 
     554           4 :   pattern_t pattern(sizespec, distspec, teamspec);
     555             : 
     556           4 :   if (_dash_id == 0) {
     557           2 :     dash::test::print_pattern_mapping(
     558             :       "matrix.pattern.unit_at", pattern, 3,
     559          90 :       [](const pattern_t & _pattern, int _x, int _y) -> dart_unit_t {
     560         180 :           return _pattern.unit_at(
     561         180 :                    std::array<index_t, 2> {{ _x, _y }});
     562           1 :       });
     563           2 :     dash::test::print_pattern_mapping(
     564             :       "matrix.pattern.at", pattern, 3,
     565          90 :       [](const pattern_t & _pattern, int _x, int _y) -> index_t {
     566          90 :           return _pattern.at(
     567          90 :                    std::array<index_t, 2> {{ _x, _y }});
     568           1 :       });
     569           2 :     dash::test::print_pattern_mapping(
     570             :       "matrix.pattern.block_at", pattern, 3,
     571          90 :       [](const pattern_t & _pattern, int _x, int _y) -> index_t {
     572         180 :           return _pattern.block_at(
     573         180 :                    std::array<index_t, 2> {{ _x, _y }});
     574           1 :       });
     575           2 :     dash::test::print_pattern_mapping(
     576             :       "matrix.pattern.block.offset", pattern, 5,
     577          90 :       [](const pattern_t & _pattern, int _x, int _y) -> std::string {
     578         180 :           auto block_idx = _pattern.block_at(
     579          90 :                              std::array<index_t, 2> {{ _x, _y }});
     580          90 :           auto block_vs  = _pattern.block(block_idx);
     581         180 :           std::ostringstream ss;
     582          90 :           ss << block_vs.offset(0) << "," << block_vs.offset(1);
     583         180 :           return ss.str();
     584           1 :       });
     585           2 :     dash::test::print_pattern_mapping(
     586             :       "matrix.pattern.local_index", pattern, 3,
     587          90 :       [](const pattern_t & _pattern, int _x, int _y) -> index_t {
     588          90 :           return _pattern.local_index(
     589         180 :                    std::array<index_t, 2> {{ _x, _y }}).index;
     590           1 :       });
     591             :   }
     592             : 
     593           8 :   matrix_t matrix_a(pattern);
     594           8 :   matrix_t matrix_b(pattern);
     595             : 
     596           4 :   auto lblockspec_a = matrix_a.pattern().local_blockspec();
     597           4 :   auto lblockspec_b = matrix_b.pattern().local_blockspec();
     598           4 :   auto blockspec_a  = matrix_a.pattern().blockspec();
     599             : //auto blockspec_b  = matrix_b.pattern().blockspec();
     600             : 
     601           4 :   size_t num_local_blocks_a = lblockspec_a.size();
     602           4 :   size_t num_local_blocks_b = lblockspec_b.size();
     603             : 
     604           4 :   ASSERT_EQ_U(num_local_blocks_a, num_local_blocks_b);
     605             : 
     606             :   LOG_MESSAGE("lblockspec_a(%lu,%lu)[%d] lblockspec_b(%lu,%lu)[%d]",
     607             :               lblockspec_a.extent(0), lblockspec_a.extent(1),
     608             :               num_local_blocks_a,
     609             :               lblockspec_b.extent(0), lblockspec_b.extent(1),
     610             :               num_local_blocks_b);
     611             : 
     612             :   // Initialize values in local blocks of matrix A:
     613          19 :   for (int lb = 0; lb < static_cast<int>(num_local_blocks_a); ++lb) {
     614          15 :     auto lblock = matrix_a.local.block(lb);
     615         105 :     for (auto lit = lblock.begin(); lit != lblock.end(); ++lit) {
     616          90 :       *lit = dash::myid() + 0.1 * lb + 0.01 * lit.pos();
     617             :     }
     618             :   }
     619             : 
     620           4 :   matrix_a.barrier();
     621             : 
     622           4 :   if (_dash_id == 0) {
     623           2 :     dash::test::print_pattern_mapping(
     624             :       "matrix.a", pattern, 3,
     625          90 :       [](const pattern_t & _pattern, int _x, int _y) -> dart_unit_t {
     626          90 :           return _pattern.unit_at(std::array<index_t, 2> {_x, _y});
     627           1 :       });
     628           1 :     dash::test::print_matrix("matrix.a", matrix_a, 2);
     629             :   }
     630             : 
     631             :   // Copy blocks of matrix A from neighbor unit into local blocks of
     632             :   // matrix B:
     633             : 
     634             :   // Request handles from asynchronous copy operations:
     635           8 :   std::vector< dash::Future<value_t*> > req_handles;
     636             :   // Local copy target pointers for later validation:
     637           8 :   std::vector< value_t* >               dst_pointers;
     638          19 :   for (int lb = 0; lb < static_cast<int>(num_local_blocks_a); ++lb) {
     639             :     // Get native pointer of local block of B as destination of copy:
     640          15 :     auto matrix_b_lblock   = matrix_b.local.block(lb);
     641          15 :     auto matrix_b_dest     = matrix_b_lblock.begin().local();
     642          15 :     auto lblock_b_offset_x = matrix_b_lblock.offset(0);
     643          15 :     auto lblock_b_offset_y = matrix_b_lblock.offset(1);
     644          15 :     auto lblock_b_gcoord_x = lblock_b_offset_x / tilesize_x;
     645          15 :     auto lblock_b_gcoord_y = lblock_b_offset_y / tilesize_y;
     646          15 :     auto block_a_gcoord_x  = (lblock_b_gcoord_x + 1) % num_blocks_x;
     647          15 :     auto block_a_gcoord_y  = (lblock_b_gcoord_y + 1) % num_blocks_y;
     648             :     auto block_a_index     = blockspec_a.at(block_a_gcoord_x,
     649          15 :                                             block_a_gcoord_y);
     650          15 :     auto gblock_a          = matrix_a.block(block_a_index);
     651             : 
     652             :     LOG_MESSAGE("local block %d: copy_async: "
     653             :                 "A.block((%d,%d):%d) -> B.block((%d,%d):%d)",
     654             :                 lb,
     655             :                 block_a_gcoord_x,  block_a_gcoord_y,  block_a_index,
     656             :                 lblock_b_gcoord_x, lblock_b_gcoord_y, lb);
     657             : 
     658          15 :     ASSERT_NE_U(nullptr, matrix_b_dest);
     659             :     auto req = dash::copy_async(gblock_a.begin(),
     660             :                                 gblock_a.end(),
     661          30 :                                 matrix_b_dest);
     662          15 :     req_handles.push_back(req);
     663          15 :     dst_pointers.push_back(matrix_b_dest);
     664             :   }
     665             : 
     666             :   // Create some CPU load
     667           4 :   double m = 123.10;
     668           4 :   double n = 234.23;
     669           4 :   double p = 322.12;
     670   200000004 :   for (size_t i = 0; i < 50000000; ++i) {
     671   200000000 :     m = (n / std::pow(p, 1.0/3.0)) + sqrt(m);
     672             :   }
     673             :   // To prevent compiler from removing work load loop in optimization:
     674             :   LOG_MESSAGE("Dummy result: %f", m);
     675             : 
     676          19 :   for (auto req : req_handles) {
     677             :     // Wait for completion of async copy operation.
     678             :     // Returns pointer to final element copied into target range:
     679          15 :     value_t * copy_dest_end   = req.get();
     680             :     // Corresponding pointer to start of copy target range, also tests
     681             :     // number of elements copied:
     682          15 :     value_t * copy_dest_begin = copy_dest_end - num_block_elem;
     683             :     // Test if correspondig start pointer is in set of start pointers used
     684             :     // for copy_async:
     685          15 :     ASSERT_TRUE_U(std::find(dst_pointers.begin(), dst_pointers.end(),
     686             :                             copy_dest_begin) != dst_pointers.end());
     687             :   }
     688             : 
     689             :   // Wait for all units to complete their copy operations:
     690           4 :   matrix_a.barrier();
     691             : 
     692           4 :   if (_dash_id == 0) {
     693           1 :     dash::test::print_matrix("matrix.b", matrix_b, 2);
     694             :   }
     695             : 
     696             :   // Validate copied values:
     697           4 :   for (int lb = 0; lb < static_cast<int>(num_local_blocks_a); ++lb) {
     698             : //  auto block_view = matrix_a.local.block(lb);
     699             :   }
     700             : }
     701             : 
     702          20 : TEST_F(CopyTest, AsyncGlobalToLocalBlock)
     703             : {
     704             :   // Copy all elements contained in a single, continuous block.
     705           4 :   const int num_elem_per_unit = 20;
     706           4 :   size_t num_elem_total       = _dash_size * num_elem_per_unit;
     707             : 
     708           8 :   dash::Array<int> array(num_elem_total, dash::BLOCKED);
     709             : 
     710             :   // Assign initial values: [ 1000, 1001, 1002, ... 2000, 2001, ... ]
     711          84 :   for (auto l = 0; l < num_elem_per_unit; ++l) {
     712          80 :     array.local[l] = ((dash::myid() + 1) * 1000) + l;
     713             :   }
     714           4 :   array.barrier();
     715             : 
     716             :   // Local range to store copy:
     717             :   int local_copy[num_elem_per_unit];
     718             : 
     719             :   // Copy values from global range to local memory.
     720             :   // All units copy first block, so unit 0 tests local-to-local copying.
     721             :   auto dest_end = dash::copy_async(array.begin(),
     722           8 :                                    array.begin() + num_elem_per_unit,
     723           8 :                                    local_copy);
     724           4 :   dest_end.wait();
     725             : 
     726           4 :   ASSERT_EQ_U(local_copy + num_elem_per_unit, dest_end.get());
     727          84 :   for (auto l = 0; l < num_elem_per_unit; ++l) {
     728          80 :     ASSERT_EQ_U(static_cast<int>(array[l]),
     729             :                 local_copy[l]);
     730             :   }
     731          12 : }
     732             : 
     733             : #if 0
     734             : // TODO
     735             : TEST_F(CopyTest, AsyncAllToLocalVector)
     736             : {
     737             :   // Copy all elements of global array into local vector:
     738             :   const int num_elem_per_unit = 20;
     739             :   size_t num_elem_total       = _dash_size * num_elem_per_unit;
     740             : 
     741             :   dash::Array<int> array(num_elem_total, dash::BLOCKED);
     742             : 
     743             :   // Assign initial values: [ 1000, 1001, 1002, ... 2000, 2001, ... ]
     744             :   for (auto l = 0; l < num_elem_per_unit; ++l) {
     745             :     array.local[l] = ((dash::myid() + 1) * 1000) + l;
     746             :   }
     747             :   array.barrier();
     748             : 
     749             :   // Local vector to store copy of global array;
     750             :   std::vector<int> local_vector;
     751             : 
     752             :   // Copy values from global range to local memory.
     753             :   // All units copy first block, so unit 0 tests local-to-local copying.
     754             :   auto future = dash::copy_async(array.begin(),
     755             :                                    array.end(),
     756             :                                    local_vector.begin());
     757             :   auto local_dest_end = future.get();
     758             : 
     759             :   ASSERT_EQ_U(num_elem_total, local_dest_end - local_vector.begin());
     760             :   for (size_t i = 0; i < array.size(); ++i) {
     761             :     ASSERT_EQ_U(static_cast<int>(array[i]), local_vector[i]);
     762             :   }
     763             : }
     764             : #endif

Generated by: LCOV version 1.12