diff --git a/dash/test/container/MatrixTest.cc b/dash/test/container/MatrixTest.cc index 911d72ce0..b2134c547 100644 --- a/dash/test/container/MatrixTest.cc +++ b/dash/test/container/MatrixTest.cc @@ -49,7 +49,7 @@ TEST_F(MatrixTest, LocalAccess) "matrix local view:", mat.local.extents()); int lcount = (myid + 1) * 1000; - dash::generate(mat.begin(), mat.end(), + dash::generate(mat.begin(), mat.end(), [&]() { return (lcount++); }); @@ -964,11 +964,83 @@ TEST_F(MatrixTest, DelayedAlloc) } } } +} + +TEST_F(MatrixTest, VariadicDelayedAlloc) +{ + + /* + * similar test as MatrixTest.DelayedAlloc but using variadic + * delayed allocation + */ + + dash::team_unit_t myid(dash::myid()); + auto num_units = dash::size(); + + if (num_units < 4) { + LOG_MESSAGE("MatrixTest.VariadicDelayedAlloc requires at least 4 units"); + return; + } + + // Default constructor creates team spec with extents (nunits, 1, 1): + dash::TeamSpec<3> teamspec; + // Automatic balancing of team spec in three dimensions: + teamspec.balance_extents(); + + // reverse team extents + auto team_extents = teamspec.extents(); + if (team_extents[0] > team_extents[2]) { + std::swap(team_extents[0], team_extents[2]); + teamspec.resize(team_extents); + } + if (myid == 0) { + DASH_LOG_TRACE_VAR("MatrixTest.VariadicDelayedAlloc", teamspec.extents()); + } - // re-allocate to test variadic allocate - mx.deallocate(); + auto num_units_i = teamspec.extent(0); + auto num_units_j = teamspec.extent(1); + auto num_units_k = teamspec.extent(2); + // Cartesian dimensions for row-major storage order: + // index (i,j,k) = Cartesian offset (z,y,x) + auto tilesize_i = 2; + auto tilesize_j = 5; + auto tilesize_k = 3; + auto blocksize = tilesize_i * tilesize_j * tilesize_k; + auto num_blocks_i = num_units_i > 1 ? 2 * num_units_i : 1; + auto num_blocks_j = num_units_j > 1 ? 3 * num_units_j : 1; + auto num_blocks_k = num_units_k > 1 ? 2 * num_units_k : 1; + auto extent_i = num_blocks_i * tilesize_i; + auto extent_j = num_blocks_j * tilesize_j; + auto extent_k = num_blocks_k * tilesize_k; + + typedef double + value_t; + typedef dash::default_index_t + index_t; + typedef dash::default_extent_t + extent_t; + typedef dash::CartesianIndexSpace<3, dash::ROW_MAJOR, index_t> + index_space_t; + + dash::barrier(); + DASH_LOG_DEBUG("MatrixTest.VariadicDelayedAlloc", + "Calling dash::Matrix default constructor"); + + dash::Matrix< + value_t, + 3, + index_t, + dash::TilePattern<3> > mx; + + ASSERT_EQ_U(num_units, teamspec.size()); + + dash::barrier(); + DASH_LOG_DEBUG("MatrixTest.DelayedAlloc", + "Calling dash::Matrix.allocate"); + + // Delayed allocation of matrix using variadic allocate(): mx.allocate( extent_i, extent_j, @@ -978,6 +1050,100 @@ TEST_F(MatrixTest, DelayedAlloc) dash::TILE(tilesize_k), teamspec ); + + auto pattern = mx.pattern(); + auto blockspec = pattern.blockspec().extents(); + auto blocksizespec = pattern.block(0).extents(); + auto n_local_blocks = pattern.local_blockspec().size(); + auto n_local_elem = n_local_blocks * blocksize; + + DASH_LOG_DEBUG_VAR("MatrixTest.VariadicDelayedAlloc", blockspec); + DASH_LOG_DEBUG_VAR("MatrixTest.VariadicDelayedAlloc", blocksizespec); + DASH_LOG_DEBUG_VAR("MatrixTest.VariadicDelayedAlloc", blocksize); + DASH_LOG_DEBUG_VAR("MatrixTest.VariadicDelayedAlloc", mx.local.extents()); + DASH_LOG_DEBUG_VAR("MatrixTest.VariadicDelayedAlloc", mx.local.offsets()); + DASH_LOG_DEBUG_VAR("MatrixTest.VariadicDelayedAlloc", n_local_blocks); + DASH_LOG_DEBUG_VAR("MatrixTest.VariadicDelayedAlloc", n_local_elem); + + ASSERT_EQ_U(mx.local.size(), n_local_elem); + + // Initialize values: + for (extent_t lbi = 0; lbi < n_local_blocks; ++lbi) { + // submatrix view on local block obtained from matrix relative to global + // memory space: + auto g_matrix_block = mx.local.block(lbi); + // index space view on local block obtained from pattern relative to + // global index space: + auto g_pattern_block = mx.pattern().local_block(myid, lbi); + + value_t * block_lbegin = g_matrix_block.lbegin(); + value_t * block_lend = g_matrix_block.lend(); + DASH_LOG_DEBUG("MatrixTest.VariadicDelayedAlloc", + "local block idx:", lbi, + "block offset:", g_matrix_block.offsets(), + "block extents:", g_matrix_block.extents(), + "block lend-lbegin:", block_lend - block_lbegin); + + // block views should be identical: + ASSERT_EQ_U(g_matrix_block.extents(), + g_pattern_block.extents()); + ASSERT_EQ_U(g_matrix_block.offsets(), + g_pattern_block.offsets()); + // element phase, canonical element offset in block: + index_t phase = 0; + for (auto lbv = block_lbegin; lbv != block_lend; ++lbv, ++phase) { + *lbv = myid + (0.01 * lbi) + (0.0001 * phase); + } + } + + mx.barrier(); + + if (myid == 0) { + dash::test::print_matrix("Matrix<3>", mx, 4); + } + + // Validate values. + // Testing view specifiers for every index explicitly, intentionally + // inefficient. + if (myid == 0) { + for (index_t i = 0; i < static_cast(extent_i); ++i) { + for (index_t j = 0; j < static_cast(extent_j); ++j) { + for (index_t k = 0; k < static_cast(extent_k); ++k) { + DASH_LOG_TRACE("MatrixTest.VariadicDelayedAlloc", + "coords:", i, j, k); + // global coordinate: + std::array gcoords {{ i, j, k }}; + // block index in global memory space: + auto block_index = mx.pattern().block_at(gcoords); + // block index in local memory space: + auto lbi = mx.pattern().local_block_at(gcoords).index; + // block at global block index: + auto block_extents = mx.pattern().block(block_index).extents(); + auto block_i_space = index_space_t(block_extents); + auto block_unit = mx.pattern().unit_at(gcoords); + // Cartesian offsets of element in block: + std::array phase_coords {{ i % tilesize_i, + j % tilesize_j, + k % tilesize_k }}; + DASH_LOG_TRACE("MatrixTest.VariadicDelayedAlloc", + "block extents:", block_extents, + "phase coords:", phase_coords); + // canonical offset of element in block: + index_t phase = block_i_space.at(phase_coords); + value_t expected = block_unit + (0.01 * lbi) + (0.0001 * phase); + value_t actual = mx[i][j][k]; + DASH_LOG_TRACE("MatrixTest.VariadicDelayedAlloc", + "coords:", i, j, k, + "block index:", block_index, + "unit:", block_unit, + "phase:", phase_coords, "=", phase, + "expected:", expected, + "actual:", actual); + EXPECT_EQ_U(expected, actual); + } + } + } + } } TEST_F(MatrixTest, PatternScope) @@ -1119,7 +1285,7 @@ TEST_F(MatrixTest, UnderfilledLocalViewSpec){ distspec, dash::Team::All(), teamspec ); narray.barrier(); - + if ( 0 == myid ) { LOG_MESSAGE("global extent is %lu x %lu", narray.extent(0), narray.extent(1)); @@ -1131,21 +1297,21 @@ TEST_F(MatrixTest, UnderfilledLocalViewSpec){ // test lbegin, lend std::fill(narray.lbegin(), narray.lend(), 1); - std::for_each(narray.lbegin(), narray.lend(), + std::for_each(narray.lbegin(), narray.lend(), [](uint32_t & el){ ASSERT_EQ_U(el, 1); }); dash::barrier(); // test local view std::fill(narray.local.begin(), narray.local.end(), 2); - std::for_each(narray.local.begin(), narray.local.end(), + std::for_each(narray.local.begin(), narray.local.end(), [](uint32_t el){ ASSERT_EQ_U(el, 2); }); - uint32_t elementsvisited = std::distance(narray.lbegin(), narray.lend()); + uint32_t elementsvisited = std::distance(narray.lbegin(), narray.lend()); auto local_elements= narray.local.extent(0) * narray.local.extent(1); - + ASSERT_EQ_U(elementsvisited, local_elements); ASSERT_EQ_U(elementsvisited, narray.local.size()); @@ -1321,17 +1487,17 @@ TEST_F(MatrixTest, ConstMatrix) DASH_LOG_DEBUG_VAR("MatrixTest.ConstMatrix", matrix.pattern().teamspec()); } - + auto const & matrix_by_ref = matrix; auto & matrix_local = matrix.local; - + dash::fill(matrix.begin(), matrix.end(), 0); dash::barrier(); - + int el = matrix(0,0); el = matrix[0][0]; ASSERT_EQ_U(el, 0); - + el = matrix.local[0][0]; ASSERT_EQ_U(el, 0); @@ -1356,7 +1522,7 @@ TEST_F(MatrixTest, ConstMatrix) // el = ++(*(matrix_by_ref.local.lbegin())); // el = ++(*(matrix_by_ref.local.row(0).lbegin())); // matrix_by_ref.local.row(0)[0] = 5; - + // test access using non-const & matrix.local matrix.barrier(); *(matrix_local.lbegin()) = 5; @@ -1523,7 +1689,7 @@ TEST_F(MatrixTest, SubViewMatrix3Dim) EXPECT_EQ_U(dim_2_ext, matrix.extent(2)); dash::fill(matrix.begin(), matrix.end(), 0.0); - + if (dash::myid() == 0) { for (int i = 0; i < matrix.extent(0); ++i) { for (int j = 0; j < matrix.extent(1); ++j) { @@ -1564,7 +1730,7 @@ TEST_F(MatrixTest, SubViewMatrix3Dim) EXPECT_EQ_U(sub_0_size, matrix[0].size()); EXPECT_EQ_U(sub_0_size, std::distance(matrix[0].begin(), matrix[0].end())); - + if (dash::myid().id == 0) { int visited = 0; for (auto it = matrix[0].begin(); it != matrix[0].end();