From 8febae85a96c87c846a4f41682bc7950b7adc51e Mon Sep 17 00:00:00 2001 From: Roger Kowalewski Date: Mon, 27 Mar 2017 11:06:33 +0200 Subject: [PATCH] Bug #346: Fix Copy CArray to Dash Array --- dash/include/dash/algorithm/Copy.h | 52 ++++++++++++++++++++++-------- dash/test/algorithm/CopyTest.cc | 19 +++++++++++ 2 files changed, 58 insertions(+), 13 deletions(-) diff --git a/dash/include/dash/algorithm/Copy.h b/dash/include/dash/algorithm/Copy.h index 368d58ed9..0fca05125 100644 --- a/dash/include/dash/algorithm/Copy.h +++ b/dash/include/dash/algorithm/Copy.h @@ -493,17 +493,42 @@ GlobOutputIt copy_impl( "l_in_last:", in_last, "g_out_first:", out_first.pos()); + + auto num_elements = std::distance(in_first, in_last); - dart_storage_t ds = dash::dart_storage(num_elements); - DASH_ASSERT_RETURNS( - dart_put_blocking( - out_first.dart_gptr(), - in_first, - ds.nelem, - ds.dtype), - DART_OK); - auto out_last = out_first + num_elements; + if (num_elements < 1) return out_first; + + auto nremaining = static_cast(num_elements); + auto pattern = out_first.pattern(); + + while (nremaining) { + // global index to local unit and index + auto local_pos = pattern.local(out_first.pos()); + // number of elements in unit + auto local_size = pattern.local_extents(team_unit_t{local_pos.unit}); + + auto ncopy = std::min( + std::initializer_list{local_size[0], + nremaining}); + + dart_storage_t ds = dash::dart_storage(ncopy); + + DASH_ASSERT_RETURNS( + dart_put_blocking( + out_first.dart_gptr(), + in_first, + ds.nelem, + ds.dtype), + DART_OK); + + std::advance(in_first, ncopy); + std::advance(out_first, ncopy); + + nremaining = std::distance(in_first, in_last); + } + + auto out_last = out_first; DASH_LOG_TRACE("dash::copy_impl >", "g_out_last:", out_last.dart_gptr()); @@ -867,7 +892,7 @@ ValueType * copy( auto total_copy_elem = in_last - in_first; // Instead of testing in_first.local() and in_last.local(), this test for - // a local-only range only requires one call to in_first.local() which + // a local-only range only requires one call to in_first.local() which // increases throughput by ~10% for local ranges. if (num_local_elem == total_copy_elem) { // Entire input range is local: @@ -1113,10 +1138,11 @@ GlobOutputIt copy( // Copy to remote elements succeeding the local subrange: if (g_l_offset_end < out_h_last.pos()) { DASH_LOG_TRACE("dash::copy", "copy to global succeeding local subrange"); + out_last = dash::internal::copy_impl( - in_first + l_elem_offset + num_local_elem, - in_last, - out_first + num_local_elem); + in_first + l_elem_offset + num_local_elem, + in_last, + out_first + num_local_elem); } } else { // All elements in output range are remote diff --git a/dash/test/algorithm/CopyTest.cc b/dash/test/algorithm/CopyTest.cc index c27b60f70..12c4013fb 100644 --- a/dash/test/algorithm/CopyTest.cc +++ b/dash/test/algorithm/CopyTest.cc @@ -803,6 +803,25 @@ TEST_F(CopyTest, AsyncGlobalToLocalBlock) } } +TEST_F(CopyTest, CArrayToDashArray) +{ + dash::Array arr(100); + + if (dash::myid() == 0) { + int buf[100]; + std::iota(buf, buf + 100, 0); + // copy local buffer to global array + dash::copy(buf, buf + 100, arr.begin()); + } + + arr.barrier(); + + if (dash::myid() == 0) { + for (size_t idx = 0; idx < 100; ++idx) { + EXPECT_EQ_U(idx, static_cast(arr[idx])); + } + } +} #if 0 // TODO TEST_F(CopyTest, AsyncAllToLocalVector)