Avoid using ArrayHandle for message exchange.

Minimizing the need to have complex serialization code in vtkm/cont.
This is first step in moving DIY serialization code out of vtkm/cont. We
need to move that to filter so we can leverage policy correctly
serialize fields.
This commit is contained in:
Utkarsh Ayachit 2018-04-19 13:25:24 -04:00 committed by Li-Ta Lo
parent d3120dc72c
commit 74c07af9d7
3 changed files with 45 additions and 42 deletions

@ -46,29 +46,5 @@ vtkm::cont::ArrayHandle<vtkm::Range> FieldRangeCompute(const vtkm::cont::MultiBl
return vtkm::cont::detail::FieldRangeComputeImpl(
multiblock, name, assoc, VTKM_DEFAULT_TYPE_LIST_TAG(), VTKM_DEFAULT_STORAGE_LIST_TAG());
}
//-----------------------------------------------------------------------------
namespace detail
{
VTKM_CONT
vtkm::cont::ArrayHandle<vtkm::Range> MergeRanges(const vtkm::cont::ArrayHandle<vtkm::Range>& a,
const vtkm::cont::ArrayHandle<vtkm::Range>& b)
{
const auto num_vals_a = a.GetNumberOfValues();
const auto num_vals_b = b.GetNumberOfValues();
if (num_vals_b == 0)
{
return a;
}
if (num_vals_a == 0)
{
return b;
}
vtkm::cont::ArrayHandle<vtkm::Range> result;
vtkm::cont::Algorithm::Transform(a, b, result, vtkm::Add());
return result;
}
} // namespace detail
}
} // namespace vtkm::cont

@ -29,10 +29,6 @@ namespace cont
namespace detail
{
VTKM_CONT
vtkm::cont::ArrayHandle<vtkm::Range> MergeRanges(const vtkm::cont::ArrayHandle<vtkm::Range>& a,
const vtkm::cont::ArrayHandle<vtkm::Range>& b);
template <typename TypeList, typename StorageList>
VTKM_CONT vtkm::cont::ArrayHandle<vtkm::Range> FieldRangeComputeImpl(
const vtkm::cont::DataSet& dataset,
@ -63,15 +59,30 @@ VTKM_CONT vtkm::cont::ArrayHandle<vtkm::Range> FieldRangeComputeImpl(
TypeList,
StorageList)
{
return std::accumulate(
std::vector<vtkm::Range> result_vector = std::accumulate(
multiblock.begin(),
multiblock.end(),
vtkm::cont::ArrayHandle<vtkm::Range>(),
[&](const vtkm::cont::ArrayHandle<vtkm::Range>& val, const vtkm::cont::DataSet& dataset) {
auto cur_range =
std::vector<vtkm::Range>(),
[&](const std::vector<vtkm::Range>& accumulated_value, const vtkm::cont::DataSet& dataset) {
vtkm::cont::ArrayHandle<vtkm::Range> block_range =
vtkm::cont::detail::FieldRangeComputeImpl(dataset, name, assoc, TypeList(), StorageList());
return vtkm::cont::detail::MergeRanges(val, cur_range);
std::vector<vtkm::Range> result = accumulated_value;
// if the current block has more components than we have seen so far,
// resize the result to fit all components.
result.resize(std::max(result.size(), static_cast<size_t>(block_range.GetNumberOfValues())));
auto portal = block_range.GetPortalConstControl();
std::transform(vtkm::cont::ArrayPortalToIteratorBegin(portal),
vtkm::cont::ArrayPortalToIteratorEnd(portal),
result.begin(),
result.begin(),
std::plus<vtkm::Range>());
return result;
});
return vtkm::cont::make_ArrayHandle(result_vector, vtkm::CopyFlag::On);
}
}
}

@ -20,7 +20,6 @@
#include <vtkm/cont/FieldRangeGlobalCompute.h>
#include <vtkm/cont/EnvironmentTracker.h>
#include <vtkm/cont/diy/Serialization.h>
// clang-format off
VTKM_THIRDPARTY_PRE_INCLUDE
@ -32,6 +31,9 @@ VTKM_THIRDPARTY_PRE_INCLUDE
VTKM_THIRDPARTY_POST_INCLUDE
// clang-format on
#include <algorithm>
#include <functional>
namespace vtkm
{
namespace cont
@ -72,25 +74,30 @@ vtkm::cont::ArrayHandle<vtkm::Range> MergeRangesGlobal(
return ranges;
}
using ArrayHandleT = vtkm::cont::ArrayHandle<vtkm::Range>;
std::vector<vtkm::Range> v_ranges(static_cast<size_t>(ranges.GetNumberOfValues()));
std::copy(vtkm::cont::ArrayPortalToIteratorBegin(ranges.GetPortalConstControl()),
vtkm::cont::ArrayPortalToIteratorEnd(ranges.GetPortalConstControl()),
v_ranges.begin());
using VectorOfRangesT = std::vector<vtkm::Range>;
diy::Master master(comm,
1,
-1,
[]() -> void* { return new ArrayHandleT(); },
[](void* ptr) { delete static_cast<ArrayHandleT*>(ptr); });
[]() -> void* { return new VectorOfRangesT(); },
[](void* ptr) { delete static_cast<VectorOfRangesT*>(ptr); });
diy::ContiguousAssigner assigner(/*num ranks*/ comm.size(), /*global-num-blocks*/ comm.size());
diy::RegularDecomposer<diy::DiscreteBounds> decomposer(
/*dim*/ 1, diy::interval(0, comm.size() - 1), comm.size());
decomposer.decompose(comm.rank(), assigner, master);
assert(master.size() == 1); // each rank will have exactly 1 block.
*master.block<ArrayHandleT>(0) = ranges;
*master.block<VectorOfRangesT>(0) = v_ranges;
diy::RegularAllReducePartners all_reduce_partners(decomposer, /*k*/ 2);
auto callback =
[](ArrayHandleT* data, const diy::ReduceProxy& srp, const diy::RegularMergePartners&) {
[](VectorOfRangesT* data, const diy::ReduceProxy& srp, const diy::RegularMergePartners&) {
const auto selfid = srp.gid();
// 1. dequeue.
std::vector<int> incoming;
@ -99,9 +106,17 @@ vtkm::cont::ArrayHandle<vtkm::Range> MergeRangesGlobal(
{
if (gid != selfid)
{
ArrayHandleT message;
VectorOfRangesT message;
srp.dequeue(gid, message);
*data = vtkm::cont::detail::MergeRanges(*data, message);
// if the number of components we've seen so far is less than those
// in the received message, resize so we can accommodate all components
// in the message. If the message has fewer components, it has no
// effect.
data->resize(std::max(data->size(), message.size()));
std::transform(
message.begin(), message.end(), data->begin(), data->begin(), std::plus<vtkm::Range>());
}
}
// 2. enqueue
@ -117,7 +132,8 @@ vtkm::cont::ArrayHandle<vtkm::Range> MergeRangesGlobal(
diy::reduce(master, assigner, all_reduce_partners, callback);
assert(master.size() == 1); // each rank will have exactly 1 block.
return *master.block<ArrayHandleT>(0);
return vtkm::cont::make_ArrayHandle(*master.block<VectorOfRangesT>(0), vtkm::CopyFlag::On);
}
} // namespace detail
}