diff --git a/dash/examples/ex.02.matrix-copy/main.cpp b/dash/examples/ex.02.matrix-copy/main.cpp new file mode 100644 index 000000000..59faccbf7 --- /dev/null +++ b/dash/examples/ex.02.matrix-copy/main.cpp @@ -0,0 +1,56 @@ + +#include + +#include +#include + +using std::cout; +using std::endl; + + +int main(int argc, char **argv) +{ + constexpr int elem_per_unit = 1000; + dash::init(&argc, &argv); + + std::vector vec(100); + std::fill(vec.begin(), vec.end(), dash::myid()); + + dash::NArray matrix; + + dash::SizeSpec<2> sizespec(dash::size(), elem_per_unit); + dash::DistributionSpec<2> distspec(dash::BLOCKED, dash::NONE); + dash::TeamSpec<2> teamspec(dash::size(), 1); + + matrix.allocate(sizespec, distspec, teamspec); + + if (dash::myid() == 0) { + // ostream<< overload for iterators is broken + // std::cout << matrix.row(1).begin() << std::endl; +// dash::copy(&vec[0], &vec[0] + vec.size(), matrix.row(1).begin() + 100); + + auto dest_range = dash::sub<0>( + 1,2, matrix); + + using globiter_t = decltype(matrix.begin()); + + cout << "matrix.row(1).begin() + 100: " + << (matrix.row(1).begin() + 100) + << endl; + cout << "sub... expression: " + << (dest_range.begin() + 100) + << endl; + cout << "view expr. cast to gptr: " + << static_cast(dest_range.begin() + 100) + << endl; + + dash::copy(&vec[0], + &vec[0] + vec.size(), + static_cast(dest_range.begin())); + } + + matrix.barrier(); + dash::finalize(); + + return 0; +} diff --git a/dash/include/dash/algorithm/Copy.h b/dash/include/dash/algorithm/Copy.h index a6bb7e2aa..21a0f3bb9 100644 --- a/dash/include/dash/algorithm/Copy.h +++ b/dash/include/dash/algorithm/Copy.h @@ -1172,9 +1172,19 @@ GlobOutputIt copy( auto in_blocks = dash::blocks(in_g_range); DASH_LOG_TRACE_VAR("dash::copy()", in_blocks); + auto l_in_blocks = dash::local(in_blocks); + DASH_LOG_TRACE_VAR("dash::copy()", in_blocks); + auto out_blocks = dash::blocks(out_g_range); DASH_LOG_TRACE_VAR("dash::copy()", out_blocks); + // Iterator to active output block: + auto out_block_it = out_blocks.begin(); + // Iterator local blocks in input range: + for (auto l_in_block : l_in_blocks) { + DASH_LOG_TRACE_VAR("dash::copy()", l_in_block); + } + // local view on in/out ranges: auto out_l_range = dash::local(out_g_range); DASH_LOG_TRACE("dash::copy()", "local(range(out_gi, out_ge)):", @@ -1192,10 +1202,13 @@ GlobOutputIt copy( DASH_LOG_TRACE("dash::copy()", "index(local(range(in_gi, in_ge))):", dash::index(in_l_range)); - // copy local to global range: - auto out_l_end = std::copy(dash::begin(in_l_range), - dash::end(in_l_range), - dash::begin(out_l_range)); + // Only sufficient if input- and output ranges have identical + // decomposition: + // + // auto out_l_end = std::copy(dash::begin(in_l_range), + // dash::end(in_l_range), + // dash::begin(out_l_range)); + return out_first + num_elements; } diff --git a/dash/include/dash/iterator/internal/IteratorBase.h b/dash/include/dash/iterator/internal/IteratorBase.h index 1abe61b36..bb9d9cf72 100644 --- a/dash/include/dash/iterator/internal/IteratorBase.h +++ b/dash/include/dash/iterator/internal/IteratorBase.h @@ -85,12 +85,12 @@ class IndexIteratorBase } derived_t & operator++() { - _pos++; + ++_pos; return derived(); } derived_t & operator--() { - _pos--; + ++_pos; return derived(); } diff --git a/dash/include/dash/view/IndexSet.h b/dash/include/dash/view/IndexSet.h index 8d420c468..939716c8c 100644 --- a/dash/include/dash/view/IndexSet.h +++ b/dash/include/dash/view/IndexSet.h @@ -1010,6 +1010,24 @@ class IndexSetLocal return this->pattern().local_extents()[shape_dim]; } + // ---- offsets --------------------------------------------------------- + +#if TODO + constexpr std::array + offsets() const { + return std::array { }; + } + + template + constexpr index_type offset() const { + return derived().offsets()[ShapeDim]; + } + + constexpr index_type offset(std::size_t shape_dim) const { + return derived().offsets()[shape_dim]; + } +#endif + // ---- size ------------------------------------------------------------ constexpr size_type size(std::size_t sub_dim) const noexcept { diff --git a/dash/include/dash/view/Origin.h b/dash/include/dash/view/Origin.h index b1e139b58..575992166 100644 --- a/dash/include/dash/view/Origin.h +++ b/dash/include/dash/view/Origin.h @@ -70,16 +70,25 @@ global_origin(const ViewT & view) template constexpr auto -origin(const ViewT & view) +origin(ViewT && view) -> typename std::enable_if< - ( dash::view_traits::is_view::value && + ( dash::view_traits< + typename std::decay::type + >::is_view::value && dash::view_traits< - typename dash::view_traits::domain_type + typename dash::view_traits< + typename std::decay::type + >::domain_type >::is_local::value ), const typename dash::view_traits::origin_type::local_type & + // typename dash::view_traits< + // typename std::decay::type + // >::origin_type::local_type >::type { // Recurse to origin of local view: - return dash::local(dash::global_origin(view.domain())); + return dash::local( + dash::global_origin( + std::forward(view).domain())); } template diff --git a/dash/include/dash/view/ViewIterator.h b/dash/include/dash/view/ViewIterator.h index 4240b8010..d776ba16a 100644 --- a/dash/include/dash/view/ViewIterator.h +++ b/dash/include/dash/view/ViewIterator.h @@ -43,6 +43,7 @@ class ViewIterator typedef typename base_t::value_type value_type; typedef typename IndexSetType::index_type index_type; typedef typename DomainIterator::pattern_type pattern_type; + typedef typename DomainIterator::local_type local_type; private: DomainIterator _domain_it; IndexSetType _index_set; @@ -91,11 +92,11 @@ class ViewIterator return (_index_set)[this->pos()]; } - constexpr const value_type * local() const { + constexpr const local_type local() const { return (_domain_it + (_index_set[this->pos()])).local(); } - inline value_type * local() { + inline local_type local() { return (_domain_it + (_index_set[this->pos()])).local(); } @@ -111,9 +112,9 @@ class ViewIterator return (_domain_it + _index_set[this->pos()]); } -// explicit operator DomainIterator() { -// return (_domain_it + _index_set[this->pos()]); -// } + explicit operator DomainIterator() { + return (_domain_it + _index_set[this->pos()]); + } constexpr const pattern_type & pattern() const { return _domain_it.pattern(); diff --git a/dash/include/dash/view/ViewMod.h b/dash/include/dash/view/ViewMod.h index 3a21e94ee..91b13877d 100644 --- a/dash/include/dash/view/ViewMod.h +++ b/dash/include/dash/view/ViewMod.h @@ -451,10 +451,12 @@ class ViewLocalMod template constexpr size_type extent() const { return _index_set.template extent(); +// return _index_set.extents()[ShapeDim]; } constexpr size_type extent(dim_t shape_dim) const { return _index_set.extent(shape_dim); +// return _index_set.extents()[shape_dim]; } // ---- offsets --------------------------------------------------------- @@ -483,7 +485,8 @@ class ViewLocalMod return iterator( dash::begin( dash::local( - const_cast(dash::origin(*this)) )), + const_cast( + dash::origin(*this)) )), _index_set, 0); } @@ -499,7 +502,8 @@ class ViewLocalMod return iterator( dash::begin( dash::local( - const_cast(dash::origin(*this)) )), + const_cast( + dash::origin(*this)) )), _index_set, _index_set.size()); } @@ -515,7 +519,8 @@ class ViewLocalMod return *iterator( dash::begin( dash::local( - const_cast(dash::origin(*this)) )), + const_cast( + dash::origin(*this)) )), _index_set, offset); } diff --git a/dash/include/dash/view/ViewMod1D.h b/dash/include/dash/view/ViewMod1D.h index 6c04df364..fda41201e 100644 --- a/dash/include/dash/view/ViewMod1D.h +++ b/dash/include/dash/view/ViewMod1D.h @@ -129,14 +129,14 @@ class ViewSubMod constexpr const_iterator end() const { return const_iterator(dash::origin(*this).begin(), - _index_set, _index_set.size()); + _index_set, _index_set.size() - 1) + 1; } iterator end() { return iterator(const_cast( dash::origin(*this) ).begin(), - _index_set, _index_set.size()); + _index_set, _index_set.size() - 1) + 1; } constexpr const_reference operator[](int offset) const { @@ -483,8 +483,6 @@ struct view_traits > { typedef IteratorRangeOrigin origin_type; typedef RangeT image_type; -//typedef typename Iterator::pattern_type pattern_type; -//typedef std::integral_constant rank; typedef std::integral_constant rank; typedef RangeT local_type; @@ -641,7 +639,7 @@ class IteratorRangeLocalOrigin global_type & global() { return dash::global(dash::domain(*this)); } -}; +}; // IteratorRangeLocalOrigin // ----------------------------------------------------------------------- // Iterator Range Origin @@ -665,8 +663,6 @@ struct view_traits > { typedef IteratorRangeOrigin origin_type; typedef IteratorRangeOrigin image_type; -//typedef typename Iterator::pattern_type pattern_type; -//typedef std::integral_constant rank; typedef std::integral_constant rank; typedef RangeT global_type; @@ -773,7 +769,7 @@ class IteratorRangeOrigin self_t & global() { return *this; } -}; +}; // IteratorRangeOrigin // ----------------------------------------------------------------------- // Iterator Range Origin (local pointers) @@ -975,7 +971,7 @@ class IteratorRangeOrigin< constexpr size_type size() const { return std::distance(_begin, _end); } -}; +}; // IteratorRangeOrigin #endif // ---------------------------------------------------------------------- @@ -994,8 +990,6 @@ struct view_traits > { typedef RangeOrigin origin_type; typedef RangeT image_type; -//typedef typename RangeOrigin::pattern_type pattern_type; -//typedef std::integral_constant rank; typedef std::integral_constant rank; typedef RangeT global_type; @@ -1047,8 +1041,6 @@ class IteratorRange typedef self_t global_type; typedef ViewLocalMod local_type; -//typedef typename RangeOrigin::pattern_type pattern_type; - typedef typename view_traits< typename std::decay::type >::is_local is_local; @@ -1073,7 +1065,9 @@ class IteratorRange // Move begin iterator first position of its iteration scope: begin - begin.pos(), // Move end iterator to end position of its iteration scope: - begin + (begin.pattern().size() - begin.pos()) )) + begin + (begin.pattern().size() - begin.pos()) + // end + )) // Convert iterator positions to sub-range index set: , _index_set(this->domain(), begin.pos(), end.pos()) { } @@ -1083,7 +1077,9 @@ class IteratorRange // Move begin iterator first position of its iteration scope: std::move(begin) - begin.pos(), // Move end iterator to end position of its iteration scope: - std::move(begin) + (begin.pattern().size() - begin.pos()) )) + std::move(begin) + (begin.pattern().size() - begin.pos()) + // std::move(end) + )) // Convert iterator positions to sub-range index set: , _index_set(this->domain(), begin.pos(), end.pos()) { } @@ -1177,7 +1173,9 @@ class IteratorRange self_t & global() { return *this; } -}; +}; // IteratorRange + +#endif // DOXYGEN // ----------------------------------------------------------------------- // dash::make_range @@ -1197,8 +1195,6 @@ make_range(Iterator && begin, Sentinel && end) { std::forward(end)); } -#endif // DOXYGEN - } // namespace dash #endif // DASH__VIEW__VIEW_MOD_1D_H__INCLUDED diff --git a/dash/include/dash/view/ViewTraits.h b/dash/include/dash/view/ViewTraits.h index b1b25ae25..288c63044 100644 --- a/dash/include/dash/view/ViewTraits.h +++ b/dash/include/dash/view/ViewTraits.h @@ -108,7 +108,6 @@ namespace detail { >::is_local::value > is_local; typedef typename ViewT::local_type local_type; -// typedef typename view_traits::local_type local_type; typedef typename ViewT::global_type global_type; typedef typename std::conditional::origin_type origin_type; typedef std::integral_constant rank; - -// typedef typename dash::view_traits::pattern_type -// pattern_type; }; /** @@ -136,13 +132,10 @@ namespace detail { typedef ContainerT image_type; typedef ContainerT global_type; typedef typename ContainerT::local_type local_type; - //typedef typename view_traits::local_type local_type; typedef typename ContainerT::index_type index_type; typedef typename ContainerT::size_type size_type; typedef typename dash::IndexSetIdentity index_set_type; -// typedef typename ContainerT::pattern_type pattern_type; - /// Whether the view type is a projection (has less dimensions than the /// view's domain type). typedef std::integral_constant is_projection; @@ -155,7 +148,6 @@ namespace detail { typedef std::integral_constant::value > is_local; typedef std::integral_constant +#include +#include + + namespace testing { namespace internal { @@ -224,6 +229,52 @@ static std::string range_str( return ss.str(); } +template +std::string nview_str( + const NViewType & nview) { + using value_t = typename NViewType::value_type; + auto view_nrows = nview.extents()[0]; + auto view_ncols = nview.extents()[1]; + auto nindex = dash::index(nview); + std::ostringstream ss; + for (int r = 0; r < view_nrows; ++r) { + for (int c = 0; c < view_ncols; ++c) { + int offset = r * view_ncols + c; + ss << std::fixed << std::setw(3) + << offset << ":" + << std::fixed << std::setw(2) + << nindex[offset] + << ":" + << std::fixed << std::setprecision(3) + << static_cast(nview[r][c]) + << " "; + } + ss << '\n'; + } + return ss.str(); +} + +template +std::string nrange_str( + const NViewType & nview) { + using value_t = typename NViewType::value_type; + auto view_nrows = nview.extents()[0]; + auto view_ncols = nview.extents()[1]; + std::ostringstream ss; + for (int r = 0; r < view_nrows; ++r) { + for (int c = 0; c < view_ncols; ++c) { + int offset = r * view_ncols + c; + ss << std::fixed << std::setw(3) + << offset << ":" + << std::fixed << std::setprecision(3) + << static_cast(nview[r][c]) + << " "; + } + ss << '\n'; + } + return ss.str(); +} + template static bool expect_range_values_equal( const RangeA & rng_a, diff --git a/dash/test/algorithm/CopyTest.cc b/dash/test/algorithm/CopyTest.cc index 7882a2942..05085bb5e 100644 --- a/dash/test/algorithm/CopyTest.cc +++ b/dash/test/algorithm/CopyTest.cc @@ -1,4 +1,6 @@ +#include "CopyTest.h" + #include #include @@ -8,15 +10,16 @@ #include #include #include + #include #include #include -#include "../TestBase.h" -#include "../TestLogHelpers.h" -#include "CopyTest.h" +#include #include +#include + TEST_F(CopyTest, BlockingGlobalToLocalBlock) @@ -466,6 +469,66 @@ TEST_F(CopyTest, AsyncLocalToGlobPtr) array.barrier(); } +TEST_F(CopyTest, BlockingLocalToGlobalBlockNDim) +{ + // Copy all elements contained in a single, continuous block. + const int num_rows_per_unit = 3; + const int num_cols_per_unit = 7; + + // Distribute row-wise, 3 rows per units: + dash::SizeSpec<2> sizespec(num_rows_per_unit * dash::size(), + num_cols_per_unit); + dash::DistributionSpec<2> distspec(dash::BLOCKED, dash::NONE); + dash::TeamSpec<2> teamspec(dash::size(), 1); + + using pattern_t = dash::BlockPattern<2>; + + dash::NArray matrix( + sizespec, distspec, dash::Team::All(), teamspec); + + std::iota(matrix.local.begin(), + matrix.local.end(), + (dash::myid() + 1) * 100); + matrix.barrier(); + + if (dash::myid() == 0) { + DASH_LOG_DEBUG("CopyTest.BlockingLocalToGlobalBlockNDim", + "initial matrix:"); + DASH_LOG_DEBUG("CopyTest.BlockingLocalToGlobalBlockNDim", + dash::test::nrange_str(matrix)); + } + + auto dest_row = ((dash::myid() + 1) * num_rows_per_unit) + % matrix.extents()[0]; + + DASH_LOG_DEBUG_VAR("CopyTest.BlockingLocalToGlobalBlockNDim", + matrix.local.row(1)); + DASH_LOG_DEBUG_VAR("CopyTest.BlockingLocalToGlobalBlockNDim", + matrix.local.row(1).begin()); + DASH_LOG_DEBUG_VAR("CopyTest.BlockingLocalToGlobalBlockNDim", + matrix.local.row(1).end()); + +// auto in_range = dash::make_range(matrix.local.row(1).begin(), +// matrix.local.row(1).end()); + + // Copy second local row into matrix row at next unit: + dash::copy(matrix.local.row(1).begin(), + matrix.local.row(1).end(), + static_cast( + dash::sub<0>( + dest_row, + dest_row + 1, + matrix).begin() + )); + + if (dash::myid() == 0) { + DASH_LOG_DEBUG("CopyTest.BlockingLocalToGlobalBlockNDim", + "result matrix:"); + DASH_LOG_DEBUG("CopyTest.BlockingLocalToGlobalBlockNDim", + dash::test::nrange_str(matrix)); + } +} + TEST_F(CopyTest, BlockingGlobalToLocalSubBlock) { // Copy all elements contained in a single, continuous block, diff --git a/dash/test/view/NViewTest.cc b/dash/test/view/NViewTest.cc index e82aa95c5..ab94c68b9 100644 --- a/dash/test/view/NViewTest.cc +++ b/dash/test/view/NViewTest.cc @@ -552,21 +552,23 @@ TEST_F(NViewTest, MatrixBlocked1DimChained) DASH_LOG_DEBUG("NViewTest.MatrixBlocked1DimChained", "== nview_rows_l"); auto nview_rows_l = dash::local(nview_rows_g); DASH_LOG_DEBUG("NViewTest.MatrixBlocked1DimChained", + "local(sub<0>(1,3, mat)):", "extents:", nview_rows_l.extents(), "offsets:", nview_rows_l.offsets()); -// EXPECT_EQ_U(2, nview_rows_l.extent<0>()); -// EXPECT_EQ_U(block_cols, nview_rows_l.extent<1>()); -// -// dash::test::print_nview("nview_rows_l", nview_rows_l); + EXPECT_EQ_U(2, nview_rows_l.extent<0>()); + EXPECT_EQ_U(block_cols, nview_rows_l.extent<1>()); + + dash::test::print_nview("nview_rows_l", nview_rows_l); DASH_LOG_DEBUG("NViewTest.MatrixBlocked1DimChained", "== nview_cols_l"); auto nview_cols_l = dash::local(nview_cols_g); DASH_LOG_DEBUG("NViewTest.MatrixBlocked1DimChained", + "local(sub<1>(2,7, mat)):", "extents:", nview_cols_l.extents(), "offsets:", nview_cols_l.offsets()); -// dash::test::print_nview("nview_cols_l", nview_cols_l); + dash::test::print_nview("nview_cols_l", nview_cols_l); } TEST_F(NViewTest, MatrixBlocked1DimSub) @@ -605,6 +607,19 @@ TEST_F(NViewTest, MatrixBlocked1DimSub) DASH_LOG_DEBUG_VAR("NViewTest.MatrixBlocked1DimSub", mat.pattern().local_size()); + // Initial plausibility check: equality of iterator on n-dim view and + // matrix view proxy iterator: + auto view_expr_it = dash::sub<0>(1,2, mat) + .begin() + 2; + auto mat_ref_glob_it = (mat.row(1).begin() + 2); + + using globiter_t = decltype(mat.begin()); + + EXPECT_EQ_U(static_cast(view_expr_it), + (mat_ref_glob_it)); + EXPECT_EQ_U(view_expr_it.dart_gptr(), + mat_ref_glob_it.dart_gptr()); + if (dash::myid() == 0) { auto all_sub = dash::sub<0>( 0, mat.extents()[0],