2018-04-05 01:13:44 +00:00
|
|
|
//============================================================================
|
|
|
|
// Copyright (c) Kitware, Inc.
|
|
|
|
// All rights reserved.
|
|
|
|
// See LICENSE.txt for details.
|
|
|
|
// 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.
|
|
|
|
//
|
|
|
|
// Copyright 2014 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
|
|
|
|
// Copyright 2014 UT-Battelle, LLC.
|
|
|
|
// Copyright 2014 Los Alamos National Security.
|
|
|
|
//
|
|
|
|
// Under the terms of Contract DE-NA0003525 with NTESS,
|
|
|
|
// the U.S. Government retains certain rights in this software.
|
|
|
|
//
|
|
|
|
// Under the terms of Contract DE-AC52-06NA25396 with Los Alamos National
|
|
|
|
// Laboratory (LANL), the U.S. Government retains certain rights in
|
|
|
|
// this software.
|
|
|
|
//============================================================================
|
|
|
|
#include <vtkm/cont/FieldRangeGlobalCompute.h>
|
|
|
|
|
|
|
|
#include <vtkm/cont/EnvironmentTracker.h>
|
|
|
|
|
|
|
|
// clang-format off
|
|
|
|
VTKM_THIRDPARTY_PRE_INCLUDE
|
|
|
|
#include <vtkm/thirdparty/diy/Configure.h>
|
|
|
|
#include VTKM_DIY(diy/decomposition.hpp)
|
|
|
|
#include VTKM_DIY(diy/master.hpp)
|
|
|
|
#include VTKM_DIY(diy/partners/all-reduce.hpp)
|
|
|
|
#include VTKM_DIY(diy/reduce.hpp)
|
|
|
|
VTKM_THIRDPARTY_POST_INCLUDE
|
|
|
|
// clang-format on
|
|
|
|
|
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
|
|
|
{
|
|
|
|
return detail::FieldRangeGlobalComputeImpl(
|
|
|
|
dataset, name, assoc, VTKM_DEFAULT_TYPE_LIST_TAG(), VTKM_DEFAULT_STORAGE_LIST_TAG());
|
|
|
|
}
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
VTKM_CONT
|
|
|
|
vtkm::cont::ArrayHandle<vtkm::Range> FieldRangeGlobalCompute(
|
|
|
|
const vtkm::cont::MultiBlock& multiblock,
|
|
|
|
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
|
|
|
{
|
|
|
|
return detail::FieldRangeGlobalComputeImpl(
|
|
|
|
multiblock, name, assoc, VTKM_DEFAULT_TYPE_LIST_TAG(), VTKM_DEFAULT_STORAGE_LIST_TAG());
|
|
|
|
}
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
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()));
|
|
|
|
std::copy(vtkm::cont::ArrayPortalToIteratorBegin(ranges.GetPortalConstControl()),
|
|
|
|
vtkm::cont::ArrayPortalToIteratorEnd(ranges.GetPortalConstControl()),
|
|
|
|
v_ranges.begin());
|
|
|
|
|
|
|
|
using VectorOfRangesT = std::vector<vtkm::Range>;
|
2018-04-05 01:13:44 +00:00
|
|
|
|
|
|
|
diy::Master master(comm,
|
|
|
|
1,
|
|
|
|
-1,
|
2018-04-19 17:25:24 +00:00
|
|
|
[]() -> void* { return new VectorOfRangesT(); },
|
|
|
|
[](void* ptr) { delete static_cast<VectorOfRangesT*>(ptr); });
|
2018-04-05 01:13:44 +00:00
|
|
|
|
|
|
|
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.
|
2018-04-19 17:25:24 +00:00
|
|
|
*master.block<VectorOfRangesT>(0) = v_ranges;
|
2018-04-05 01:13:44 +00:00
|
|
|
|
|
|
|
diy::RegularAllReducePartners all_reduce_partners(decomposer, /*k*/ 2);
|
|
|
|
|
|
|
|
auto callback =
|
2018-04-19 17:25:24 +00:00
|
|
|
[](VectorOfRangesT* data, const diy::ReduceProxy& srp, const diy::RegularMergePartners&) {
|
2018-04-05 01:13:44 +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-19 17:25:24 +00:00
|
|
|
VectorOfRangesT message;
|
2018-04-05 01:13:44 +00:00
|
|
|
srp.dequeue(gid, message);
|
2018-04-19 17:25:24 +00:00
|
|
|
|
|
|
|
// 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
|
|
|
}
|
|
|
|
}
|
|
|
|
// 2. enqueue
|
|
|
|
for (int cc = 0; cc < srp.out_link().size(); ++cc)
|
|
|
|
{
|
|
|
|
auto target = srp.out_link().target(cc);
|
|
|
|
if (target.gid != selfid)
|
|
|
|
{
|
|
|
|
srp.enqueue(target, *data);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
diy::reduce(master, assigner, all_reduce_partners, callback);
|
|
|
|
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
|