2018-04-05 01:13:44 +00:00
|
|
|
//============================================================================
|
|
|
|
// Copyright (c) Kitware, Inc.
|
|
|
|
// All rights reserved.
|
|
|
|
// See LICENSE.txt for details.
|
2019-04-15 23:24:21 +00:00
|
|
|
//
|
2018-04-05 01:13:44 +00:00
|
|
|
// This software is distributed WITHOUT ANY WARRANTY; without even
|
|
|
|
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
|
|
|
// PURPOSE. See the above copyright notice for more information.
|
|
|
|
//============================================================================
|
|
|
|
#include <vtkm/cont/FieldRangeGlobalCompute.h>
|
|
|
|
|
|
|
|
#include <vtkm/cont/EnvironmentTracker.h>
|
|
|
|
|
2019-02-05 16:02:29 +00:00
|
|
|
#include <vtkm/thirdparty/diy/diy.h>
|
2018-04-05 01:13:44 +00:00
|
|
|
|
2018-04-19 17:25:24 +00:00
|
|
|
#include <algorithm>
|
|
|
|
#include <functional>
|
|
|
|
|
2018-04-05 01:13:44 +00:00
|
|
|
namespace vtkm
|
|
|
|
{
|
|
|
|
namespace cont
|
|
|
|
{
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
VTKM_CONT
|
2018-05-18 20:10:15 +00:00
|
|
|
vtkm::cont::ArrayHandle<vtkm::Range> FieldRangeGlobalCompute(const vtkm::cont::DataSet& dataset,
|
|
|
|
const std::string& name,
|
|
|
|
vtkm::cont::Field::Association assoc)
|
2018-04-05 01:13:44 +00:00
|
|
|
{
|
2019-12-05 17:55:57 +00:00
|
|
|
return detail::FieldRangeGlobalComputeImpl(dataset, name, assoc, VTKM_DEFAULT_TYPE_LIST());
|
2018-04-05 01:13:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
VTKM_CONT
|
|
|
|
vtkm::cont::ArrayHandle<vtkm::Range> FieldRangeGlobalCompute(
|
2019-09-02 14:38:47 +00:00
|
|
|
const vtkm::cont::PartitionedDataSet& pds,
|
2018-04-05 01:13:44 +00:00
|
|
|
const std::string& name,
|
2018-05-18 20:10:15 +00:00
|
|
|
vtkm::cont::Field::Association assoc)
|
2018-04-05 01:13:44 +00:00
|
|
|
{
|
2019-12-05 17:55:57 +00:00
|
|
|
return detail::FieldRangeGlobalComputeImpl(pds, name, assoc, VTKM_DEFAULT_TYPE_LIST());
|
2018-04-05 01:13:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
namespace detail
|
|
|
|
{
|
|
|
|
VTKM_CONT
|
|
|
|
vtkm::cont::ArrayHandle<vtkm::Range> MergeRangesGlobal(
|
|
|
|
const vtkm::cont::ArrayHandle<vtkm::Range>& ranges)
|
|
|
|
{
|
|
|
|
auto comm = vtkm::cont::EnvironmentTracker::GetCommunicator();
|
|
|
|
if (comm.size() == 1)
|
|
|
|
{
|
|
|
|
return ranges;
|
|
|
|
}
|
|
|
|
|
2018-04-19 17:25:24 +00:00
|
|
|
std::vector<vtkm::Range> v_ranges(static_cast<size_t>(ranges.GetNumberOfValues()));
|
2020-01-28 19:14:32 +00:00
|
|
|
std::copy(vtkm::cont::ArrayPortalToIteratorBegin(ranges.ReadPortal()),
|
|
|
|
vtkm::cont::ArrayPortalToIteratorEnd(ranges.ReadPortal()),
|
2018-04-19 17:25:24 +00:00
|
|
|
v_ranges.begin());
|
|
|
|
|
|
|
|
using VectorOfRangesT = std::vector<vtkm::Range>;
|
2018-04-05 01:13:44 +00:00
|
|
|
|
2020-08-17 14:18:24 +00:00
|
|
|
vtkmdiy::Master master(
|
|
|
|
comm,
|
|
|
|
1,
|
|
|
|
-1,
|
|
|
|
[]() -> void* { return new VectorOfRangesT(); },
|
|
|
|
[](void* ptr) { delete static_cast<VectorOfRangesT*>(ptr); });
|
2018-04-05 01:13:44 +00:00
|
|
|
|
2019-02-05 16:02:29 +00:00
|
|
|
vtkmdiy::ContiguousAssigner assigner(/*num ranks*/ comm.size(),
|
|
|
|
/*global-num-blocks*/ comm.size());
|
|
|
|
vtkmdiy::RegularDecomposer<vtkmdiy::DiscreteBounds> decomposer(
|
|
|
|
/*dim*/ 1, vtkmdiy::interval(0, comm.size() - 1), comm.size());
|
2018-04-05 01:13:44 +00:00
|
|
|
decomposer.decompose(comm.rank(), assigner, master);
|
|
|
|
assert(master.size() == 1); // each rank will have exactly 1 block.
|
2018-04-19 17:25:24 +00:00
|
|
|
*master.block<VectorOfRangesT>(0) = v_ranges;
|
2018-04-05 01:13:44 +00:00
|
|
|
|
2019-02-05 16:02:29 +00:00
|
|
|
vtkmdiy::RegularAllReducePartners all_reduce_partners(decomposer, /*k*/ 2);
|
|
|
|
|
2020-08-17 14:18:24 +00:00
|
|
|
auto callback = [](VectorOfRangesT* data,
|
|
|
|
const vtkmdiy::ReduceProxy& srp,
|
|
|
|
const vtkmdiy::RegularMergePartners&) {
|
2019-02-05 16:02:29 +00:00
|
|
|
const auto selfid = srp.gid();
|
|
|
|
// 1. dequeue.
|
|
|
|
std::vector<int> incoming;
|
|
|
|
srp.incoming(incoming);
|
|
|
|
for (const int gid : incoming)
|
|
|
|
{
|
|
|
|
if (gid != selfid)
|
2018-04-05 01:13:44 +00:00
|
|
|
{
|
2019-02-05 16:02:29 +00:00
|
|
|
VectorOfRangesT message;
|
|
|
|
srp.dequeue(gid, 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>());
|
2018-04-05 01:13:44 +00:00
|
|
|
}
|
2019-02-05 16:02:29 +00:00
|
|
|
}
|
|
|
|
// 2. enqueue
|
|
|
|
for (int cc = 0; cc < srp.out_link().size(); ++cc)
|
|
|
|
{
|
|
|
|
auto target = srp.out_link().target(cc);
|
|
|
|
if (target.gid != selfid)
|
2018-04-05 01:13:44 +00:00
|
|
|
{
|
2019-02-05 16:02:29 +00:00
|
|
|
srp.enqueue(target, *data);
|
2018-04-05 01:13:44 +00:00
|
|
|
}
|
2019-02-05 16:02:29 +00:00
|
|
|
}
|
|
|
|
};
|
2018-04-05 01:13:44 +00:00
|
|
|
|
2019-02-05 16:02:29 +00:00
|
|
|
vtkmdiy::reduce(master, assigner, all_reduce_partners, callback);
|
2018-04-05 01:13:44 +00:00
|
|
|
assert(master.size() == 1); // each rank will have exactly 1 block.
|
2018-04-19 17:25:24 +00:00
|
|
|
|
|
|
|
return vtkm::cont::make_ArrayHandle(*master.block<VectorOfRangesT>(0), vtkm::CopyFlag::On);
|
2018-04-05 01:13:44 +00:00
|
|
|
}
|
|
|
|
} // namespace detail
|
|
|
|
}
|
|
|
|
} // namespace vtkm::cont
|