From 05e5d40f8eef5a7f368024bdbc0116c920052e03 Mon Sep 17 00:00:00 2001 From: Li-Ta Lo Date: Thu, 19 Oct 2017 11:44:36 -0600 Subject: [PATCH 1/3] PointLocatorUniformGrid Provide an accelerated neareast neighbor search of points in the dataset using a one layer uniform grid. --- vtkm/cont/CMakeLists.txt | 1 + vtkm/cont/PointLocatorUniformGrid.h | 237 ++++++++++++++++++ vtkm/cont/cuda/testing/CMakeLists.txt | 1 + .../UnitTestCudaPointLocatorUniformGrid.cxx | 26 ++ vtkm/cont/serial/testing/CMakeLists.txt | 1 + .../UnitTestSerialPointLocatorUniformGrid.cxx | 26 ++ vtkm/cont/tbb/testing/CMakeLists.txt | 1 + .../UnitTestTBBPointLocatorUniformGrid.cxx | 26 ++ vtkm/cont/testing/CMakeLists.txt | 1 + .../testing/TestingPointLocatorUniformGrid.h | 148 +++++++++++ 10 files changed, 468 insertions(+) create mode 100644 vtkm/cont/PointLocatorUniformGrid.h create mode 100644 vtkm/cont/cuda/testing/UnitTestCudaPointLocatorUniformGrid.cxx create mode 100644 vtkm/cont/serial/testing/UnitTestSerialPointLocatorUniformGrid.cxx create mode 100644 vtkm/cont/tbb/testing/UnitTestTBBPointLocatorUniformGrid.cxx create mode 100644 vtkm/cont/testing/TestingPointLocatorUniformGrid.h diff --git a/vtkm/cont/CMakeLists.txt b/vtkm/cont/CMakeLists.txt index 581270ba2..9a20f8aa2 100644 --- a/vtkm/cont/CMakeLists.txt +++ b/vtkm/cont/CMakeLists.txt @@ -71,6 +71,7 @@ set(headers Field.h ImplicitFunction.h MultiBlock.h + PointLocatorUniformGrid.h RuntimeDeviceInformation.h RuntimeDeviceTracker.h Storage.h diff --git a/vtkm/cont/PointLocatorUniformGrid.h b/vtkm/cont/PointLocatorUniformGrid.h new file mode 100644 index 000000000..e7ac94d3f --- /dev/null +++ b/vtkm/cont/PointLocatorUniformGrid.h @@ -0,0 +1,237 @@ +//============================================================================ +// 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 2017 National Technology & Engineering Solutions of Sandia, LLC (NTESS). +// Copyright 2014 UT-Battelle, LLC. +// Copyright 2017 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. +//============================================================================ + +#ifndef vtk_m_cont_PointLocatorUniformGrid_h +#define vtk_m_cont_PointLocatorUniformGrid_h + +#include +#include +#include +#include +#include + +namespace vtkm +{ +namespace worklet +{ +template +class PointLocatorUniformGrid +{ +public: + PointLocatorUniformGrid(const vtkm::Vec& _min, + const vtkm::Vec& _max, + const vtkm::Vec& _dims) + : min(_min) + , max(_max) + , dims(_dims) + { + } + + class BinPointsWorklet : public vtkm::worklet::WorkletMapField + { + public: + typedef void ControlSignature(FieldIn<> coord, FieldOut<> label); + + typedef void ExecutionSignature(_1, _2); + + VTKM_CONT + BinPointsWorklet(vtkm::Vec _min, vtkm::Vec _max, vtkm::Vec _dims) + : min(_min) + , dims(_dims) + , dxdydz((_max - min) / dims) + { + } + + template + VTKM_EXEC void operator()(const CoordVecType& coord, IdType& label) const + { + vtkm::Vec ijk = (coord - min) / dxdydz; + label = ijk[0] + ijk[1] * dims[0] + ijk[2] * dims[0] * dims[1]; + } + + private: + vtkm::Vec min; + vtkm::Vec dims; + vtkm::Vec dxdydz; + }; + + class UniformGridSearch : public vtkm::worklet::WorkletMapField + { + public: + typedef void ControlSignature(FieldIn<> query, + WholeArrayIn<> coordIn, + WholeArrayIn pointId, + WholeArrayIn cellLower, + WholeArrayIn cellUpper, + FieldOut neighborId, + FieldOut<> distance); + + typedef void ExecutionSignature(_1, _2, _3, _4, _5, _6, _7); + + VTKM_CONT + UniformGridSearch(const vtkm::Vec& _min, + const vtkm::Vec& _max, + const vtkm::Vec& _dims) + : min(_min) + , dims(_dims) + , dxdydz((_max - _min) / _dims) + { + } + + + template + VTKM_EXEC void operator()(const CoordiVecType& queryCoord, + const CoordiPortalType& coordi_Handle, + const IdPortalType& pointId, + const IdPortalType& cellLower, + const IdPortalType& cellUpper, + IdType& nnId, + CoordiType& nnDis) const + { + auto nlayers = vtkm::Max(vtkm::Max(dims[0], dims[1]), dims[2]); + + vtkm::Vec xyz = (queryCoord - min) / dxdydz; + + float min_distance = std::numeric_limits::max(); + vtkm::Id neareast = -1; + + for (vtkm::Id layer = 0; layer < nlayers; layer++) + { + vtkm::Id minx = vtkm::Max(vtkm::Id(), xyz[0] - layer); + vtkm::Id maxx = vtkm::Min(dims[0] - 1, xyz[0] + layer); + vtkm::Id miny = vtkm::Max(vtkm::Id(), xyz[1] - layer); + vtkm::Id maxy = vtkm::Min(dims[1] - 1, xyz[1] + layer); + vtkm::Id minz = vtkm::Max(vtkm::Id(), xyz[2] - layer); + vtkm::Id maxz = vtkm::Min(dims[2] - 1, xyz[2] + layer); + + for (auto i = minx; i <= maxx; i++) + { + for (auto j = miny; j <= maxy; j++) + { + for (auto k = minz; k <= maxz; k++) + { + if (i == (xyz[0] + layer) || i == (xyz[0] - layer) || j == (xyz[1] + layer) || + j == (xyz[1] - layer) || k == (xyz[2] + layer) || k == (xyz[2] - layer)) + { + auto cellid = i + j * dims[0] + k * dims[0] * dims[1]; + auto lower = cellLower.Get(cellid); + auto upper = cellUpper.Get(cellid); + for (auto index = lower; index < upper; index++) + { + auto pointid = pointId.Get(index); + auto point = coordi_Handle.Get(pointid); + auto dx = point[0] - queryCoord[0]; + auto dy = point[1] - queryCoord[1]; + auto dz = point[2] - queryCoord[2]; + + auto distance2 = dx * dx + dy * dy + dz * dz; + if (distance2 < min_distance) + { + neareast = pointid; + min_distance = distance2; + nlayers = layer + 2; + } + } + } + } + } + } + } + + nnId = neareast; + nnDis = vtkm::Sqrt(min_distance); + }; + + private: + vtkm::Vec min; + vtkm::Vec dims; + vtkm::Vec dxdydz; + }; + + /// \brief Construct a 3D uniform grid for nearest neighbor search. + /// + /// \param coords An ArrayHandle of x, y, z coordinates of input points. + /// \param device Tag for selecting device adapter + template + void Build(const vtkm::cont::ArrayHandle>& coords, DeviceAdapter) + { + typedef vtkm::cont::DeviceAdapterAlgorithm Algorithm; + // generate unique id for each input point + vtkm::cont::ArrayHandleCounting pointCounting(0, 1, coords.GetNumberOfValues()); + Algorithm::Copy(pointCounting, pointIds); + + // bin points into cells and give each of them the cell id. + BinPointsWorklet cellIdWorklet(min, max, dims); + vtkm::worklet::DispatcherMapField dispatchCellId(cellIdWorklet); + dispatchCellId.Invoke(coords, cellIds); + + // Group points of the same cell together by sorting them according to the cell ids + Algorithm::SortByKey(cellIds, pointIds); + + // for each cell, find the lower and upper bound of indices to the sorted point ids. + vtkm::cont::ArrayHandleCounting cell_ids_counting(0, 1, dims[0] * dims[1] * dims[2]); + Algorithm::UpperBounds(cellIds, cell_ids_counting, cellUpper); + Algorithm::LowerBounds(cellIds, cell_ids_counting, cellLower); + }; + + /// \brief Nearest neighbor search using a Uniform Grid + /// + /// Parallel search of nearesat neighbor for each point in the \c queryPoints in the set of + /// \c coords. Returns neareast neighbot in \c nearestNeighborIds and distances to nearest + /// neighbor in \c distances. + /// + /// \param coords Point coordinates for training dataset. + /// \param queryPoints Point coordinates to query for nearest neighbors. + /// \param nearestNeighborIds Neareast neighbor in the training dataset for each points in + /// the test set + /// \param distances Distance between query points and their nearest neighbors. + /// \param device Tag for selecting device adapter. + template + void Run(const vtkm::cont::ArrayHandle>& coords, + const vtkm::cont::ArrayHandle>& queryPoints, + vtkm::cont::ArrayHandle& nearestNeighborIds, + vtkm::cont::ArrayHandle& distances, + DeviceAdapter) + { + UniformGridSearch uniformGridSearch(min, max, dims); + + vtkm::worklet::DispatcherMapField searchDispatcher( + uniformGridSearch); + searchDispatcher.Invoke( + queryPoints, coords, pointIds, cellLower, cellUpper, nearestNeighborIds, distances); + }; + +private: + vtkm::Vec min; + vtkm::Vec max; + vtkm::Vec dims; + + vtkm::cont::ArrayHandle pointIds; + vtkm::cont::ArrayHandle cellIds; + vtkm::cont::ArrayHandle cellLower; + vtkm::cont::ArrayHandle cellUpper; +}; +} +} +#endif //vtk_m_cont_PointLocatorUniformGrid_h diff --git a/vtkm/cont/cuda/testing/CMakeLists.txt b/vtkm/cont/cuda/testing/CMakeLists.txt index 01dbfe440..924c15793 100644 --- a/vtkm/cont/cuda/testing/CMakeLists.txt +++ b/vtkm/cont/cuda/testing/CMakeLists.txt @@ -28,6 +28,7 @@ set(unit_tests UnitTestCudaImplicitFunction.cu UnitTestCudaMath.cu UnitTestCudaShareUserProvidedManagedMemory.cu + UnitTestCudaPointLocatorUniformGrid.cxx UnitTestCudaVirtualObjectCache.cu ) vtkm_unit_tests(CUDA SOURCES ${unit_tests}) diff --git a/vtkm/cont/cuda/testing/UnitTestCudaPointLocatorUniformGrid.cxx b/vtkm/cont/cuda/testing/UnitTestCudaPointLocatorUniformGrid.cxx new file mode 100644 index 000000000..017aecca3 --- /dev/null +++ b/vtkm/cont/cuda/testing/UnitTestCudaPointLocatorUniformGrid.cxx @@ -0,0 +1,26 @@ +//============================================================================ +// 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 2017 National Technology & Engineering Solutions of Sandia, LLC (NTESS). +// Copyright 2017 UT-Battelle, LLC. +// Copyright 2017 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 + +int UnitTestCudaPointLocatorUniformGrid(int, char* []) +{ + return vtkm::cont::testing::Testing::Run( + TestingPointLocatorUniformGrid()); +} diff --git a/vtkm/cont/serial/testing/CMakeLists.txt b/vtkm/cont/serial/testing/CMakeLists.txt index 0bf236bc7..983ccbf80 100644 --- a/vtkm/cont/serial/testing/CMakeLists.txt +++ b/vtkm/cont/serial/testing/CMakeLists.txt @@ -27,6 +27,7 @@ set(unit_tests UnitTestSerialDataSetSingleType.cxx UnitTestSerialDeviceAdapter.cxx UnitTestSerialImplicitFunction.cxx + UnitTestSerialPointLocatorUniformGrid.cxx UnitTestSerialVirtualObjectCache.cxx ) vtkm_unit_tests(TBB SOURCES ${unit_tests}) diff --git a/vtkm/cont/serial/testing/UnitTestSerialPointLocatorUniformGrid.cxx b/vtkm/cont/serial/testing/UnitTestSerialPointLocatorUniformGrid.cxx new file mode 100644 index 000000000..90afda937 --- /dev/null +++ b/vtkm/cont/serial/testing/UnitTestSerialPointLocatorUniformGrid.cxx @@ -0,0 +1,26 @@ +//============================================================================ +// 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 2017 National Technology & Engineering Solutions of Sandia, LLC (NTESS). +// Copyright 2017 UT-Battelle, LLC. +// Copyright 2017 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 + +int UnitTestSerialPointLocatorUniformGrid(int, char* []) +{ + return vtkm::cont::testing::Testing::Run( + TestingPointLocatorUniformGrid()); +} diff --git a/vtkm/cont/tbb/testing/CMakeLists.txt b/vtkm/cont/tbb/testing/CMakeLists.txt index a62955682..38b793c8b 100644 --- a/vtkm/cont/tbb/testing/CMakeLists.txt +++ b/vtkm/cont/tbb/testing/CMakeLists.txt @@ -27,6 +27,7 @@ set(unit_tests UnitTestTBBDataSetSingleType.cxx UnitTestTBBDeviceAdapter.cxx UnitTestTBBImplicitFunction.cxx + UnitTestTBBPointLocatorUniformGrid.cxx UnitTestTBBVirtualObjectCache.cxx ) vtkm_unit_tests(TBB SOURCES ${unit_tests}) diff --git a/vtkm/cont/tbb/testing/UnitTestTBBPointLocatorUniformGrid.cxx b/vtkm/cont/tbb/testing/UnitTestTBBPointLocatorUniformGrid.cxx new file mode 100644 index 000000000..37a740b49 --- /dev/null +++ b/vtkm/cont/tbb/testing/UnitTestTBBPointLocatorUniformGrid.cxx @@ -0,0 +1,26 @@ +//============================================================================ +// 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 2017 National Technology & Engineering Solutions of Sandia, LLC (NTESS). +// Copyright 2017 UT-Battelle, LLC. +// Copyright 2017 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 + +int UnitTestTBBPointLocatorUniformGrid(int, char* []) +{ + return vtkm::cont::testing::Testing::Run( + TestingPointLocatorUniformGrid()); +} diff --git a/vtkm/cont/testing/CMakeLists.txt b/vtkm/cont/testing/CMakeLists.txt index 0cfa3070b..a5efd683c 100644 --- a/vtkm/cont/testing/CMakeLists.txt +++ b/vtkm/cont/testing/CMakeLists.txt @@ -30,6 +30,7 @@ set(headers TestingDataSetSingleType.h TestingFancyArrayHandles.h TestingImplicitFunction.h + TestingPointLocatorUniformGrid.h TestingVirtualObjectCache.h ) diff --git a/vtkm/cont/testing/TestingPointLocatorUniformGrid.h b/vtkm/cont/testing/TestingPointLocatorUniformGrid.h new file mode 100644 index 000000000..cae1471ec --- /dev/null +++ b/vtkm/cont/testing/TestingPointLocatorUniformGrid.h @@ -0,0 +1,148 @@ +//============================================================================ +// 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 2017 National Technology & Engineering Solutions of Sandia, LLC (NTESS). +// Copyright 2014 UT-Battelle, LLC. +// Copyright 2017 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. +//============================================================================ + +#ifndef vtk_m_cont_testing_TestingPointLocatorUniformGrid_h +#define vtk_m_cont_testing_TestingPointLocatorUniformGrid_h + +#include + +#include + +#include + +////brute force method ///// +template +VTKM_EXEC_CONT vtkm::Id NNSVerify3D(CoordiVecT qc, CoordiPortalT coordiPortal, CoordiT& dis) +{ + dis = std::numeric_limits::max(); + vtkm::Id nnpIdx = -1; + + for (vtkm::Int32 i = 0; i < coordiPortal.GetNumberOfValues(); i++) + { + CoordiT splitX = coordiPortal.Get(i)[0]; + CoordiT splitY = coordiPortal.Get(i)[1]; + CoordiT splitZ = coordiPortal.Get(i)[2]; + CoordiT _dis = + vtkm::Sqrt((splitX - qc[0]) * (splitX - qc[0]) + (splitY - qc[1]) * (splitY - qc[1]) + + (splitZ - qc[2]) * (splitZ - qc[2])); + if (_dis < dis) + { + dis = _dis; + nnpIdx = i; + } + } + return nnpIdx; +} + +class NearestNeighborSearchBruteForce3DWorklet : public vtkm::worklet::WorkletMapField +{ +public: + typedef void ControlSignature(FieldIn<> qcIn, + WholeArrayIn<> treeCoordiIn, + FieldOut<> nnIdOut, + FieldOut<> nnDisOut); + typedef void ExecutionSignature(_1, _2, _3, _4); + + VTKM_CONT + NearestNeighborSearchBruteForce3DWorklet() {} + + template + VTKM_EXEC void operator()(const CoordiVecType& qc, + const CoordiPortalType& coordiPortal, + IdType& nnId, + CoordiType& nnDis) const + { + nnDis = std::numeric_limits::max(); + + nnId = NNSVerify3D(qc, coordiPortal, nnDis); + } +}; + +template +class TestingPointLocatorUniformGrid +{ +public: + typedef vtkm::cont::DeviceAdapterAlgorithm Algorithm; + void TestTest() const + { + vtkm::Int32 nTrainingPoints = 1000; + vtkm::Int32 nTestingPoint = 1000; + + std::vector> coordi; + + ///// randomly generate training points///// + std::default_random_engine dre; + std::uniform_real_distribution dr(0.0f, 10.0f); + + for (vtkm::Int32 i = 0; i < nTrainingPoints; i++) + { + coordi.push_back(vtkm::make_Vec(dr(dre), dr(dre), dr(dre))); + } + auto coordi_Handle = vtkm::cont::make_ArrayHandle(coordi); + + vtkm::worklet::PointLocatorUniformGrid uniformGrid( + { 0.0f, 0.0f, 0.0f }, { 10.0f, 10.0f, 10.0f }, { 5, 5, 5 }); + uniformGrid.Build(coordi_Handle, VTKM_DEFAULT_DEVICE_ADAPTER_TAG()); + + std::vector> qcVec; + for (vtkm::Int32 i = 0; i < nTestingPoint; i++) + { + qcVec.push_back(vtkm::make_Vec(dr(dre), dr(dre), dr(dre))); + } + auto qc_Handle = vtkm::cont::make_ArrayHandle(qcVec); + + vtkm::cont::ArrayHandle nnId_Handle; + vtkm::cont::ArrayHandle nnDis_Handle; + + uniformGrid.Run( + coordi_Handle, qc_Handle, nnId_Handle, nnDis_Handle, VTKM_DEFAULT_DEVICE_ADAPTER_TAG()); + + vtkm::cont::ArrayHandle bfnnId_Handle; + vtkm::cont::ArrayHandle bfnnDis_Handle; + NearestNeighborSearchBruteForce3DWorklet nnsbf3dWorklet; + vtkm::worklet::DispatcherMapField nnsbf3DDispatcher( + nnsbf3dWorklet); + nnsbf3DDispatcher.Invoke( + qc_Handle, vtkm::cont::make_ArrayHandle(coordi), bfnnId_Handle, bfnnDis_Handle); + + ///// verfity search result ///// + bool passTest = true; + for (vtkm::Int32 i = 0; i < nTestingPoint; i++) + { + vtkm::Id workletIdx = nnId_Handle.GetPortalControl().Get(i); + vtkm::Float32 workletDis = nnDis_Handle.GetPortalConstControl().Get(i); + vtkm::Id bfworkletIdx = bfnnId_Handle.GetPortalControl().Get(i); + vtkm::Float32 bfworkletDis = bfnnDis_Handle.GetPortalConstControl().Get(i); + + if (workletIdx != bfworkletIdx) + { + std::cout << "bf index: " << bfworkletIdx << ", dis: " << bfworkletDis + << ", grid: " << workletIdx << ", dis " << workletDis << std::endl; + passTest = false; + } + } + + VTKM_TEST_ASSERT(false, "Uniform Grid NN search result incorrect."); + } + + void operator()() const { this->TestTest(); } +}; + +#endif // vtk_m_cont_testing_TestingPointLocatorUniformGrid_h From c27528d8842ac34a42fbb50c0cd96fe96b9c8eab Mon Sep 17 00:00:00 2001 From: Li-Ta Lo Date: Thu, 3 May 2018 13:57:44 -0600 Subject: [PATCH 2/3] Extract neareast neighbor search functionality into an ExecutionObject Modify PointLocatorUniform::Build to return an ExecutionObjec, Locator. The Locator can the be passed to Worklets for finding neareast neighbor point by calling the FindNeareastPoint method. --- vtkm/cont/PointLocatorUniformGrid.h | 126 +++++++++--------- .../testing/TestingPointLocatorUniformGrid.h | 36 ++++- 2 files changed, 95 insertions(+), 67 deletions(-) diff --git a/vtkm/cont/PointLocatorUniformGrid.h b/vtkm/cont/PointLocatorUniformGrid.h index 73e8d5f5c..90c75b213 100644 --- a/vtkm/cont/PointLocatorUniformGrid.h +++ b/vtkm/cont/PointLocatorUniformGrid.h @@ -28,7 +28,7 @@ namespace vtkm { -namespace worklet +namespace cont { template class PointLocatorUniformGrid @@ -71,46 +71,56 @@ public: vtkm::Vec Dxdydz; }; - class UniformGridSearch : public vtkm::worklet::WorkletMapField + template + class Locator : public vtkm::exec::ExecutionObjectBase { public: - typedef void ControlSignature(FieldIn<> query, - WholeArrayIn<> coordIn, - WholeArrayIn pointId, - WholeArrayIn cellLower, - WholeArrayIn cellUpper, - FieldOut neighborId, - FieldOut<> distance); - - typedef void ExecutionSignature(_1, _2, _3, _4, _5, _6, _7); + using CoordPortalType = typename vtkm::cont::ArrayHandle< + vtkm::Vec>::template ExecutionTypes::PortalConst; + using IdPortalType = typename vtkm::cont::ArrayHandle::template ExecutionTypes< + DeviceAdapter>::PortalConst; VTKM_CONT - UniformGridSearch(const vtkm::Vec& _min, - const vtkm::Vec& _max, - const vtkm::Vec& _dims) + Locator() = default; + + VTKM_CONT + Locator(const vtkm::Vec& _min, + const vtkm::Vec& _max, + const vtkm::Vec& _dims, + const CoordPortalType& coords, + const IdPortalType& pointIds, + const IdPortalType& cellLower, + const IdPortalType& cellUpper) : Min(_min) , Dims(_dims) - , Dxdydz((_max - _min) / _dims) + , Dxdydz((_max - Min) / Dims) + , coords(coords) + , pointIds(pointIds) + , cellLower(cellLower) + , cellUpper(cellUpper) { } - - template - VTKM_EXEC void operator()(const CoordiVecType& queryCoord, - const CoordiPortalType& coordi_Handle, - const IdPortalType& pointId, - const IdPortalType& cellLower, - const IdPortalType& cellUpper, - IdType& nnId, - CoordiType& nnDis) const + /// \brief Nearest neighbor search using a Uniform Grid + /// + /// Parallel search of nearesat neighbor for each point in the \c queryPoints in the set of + /// \c coords. Returns neareast neighbot in \c nearestNeighborIds and distances to nearest + /// neighbor in \c distances. + /// + /// \param coords Point coordinates for training dataset. + /// \param queryPoints Point coordinates to query for nearest neighbors. + /// \param nearestNeighborIds Neareast neighbor in the training dataset for each points in + /// the test set + /// \param distances Distance between query points and their nearest neighbors. + /// \param device Tag for selecting device adapter. + VTKM_EXEC + void FindNearestPoint(const vtkm::Vec& queryPoint, + vtkm::Id& nearestNeighborId, + T& distance) const { auto nlayers = vtkm::Max(vtkm::Max(Dims[0], Dims[1]), Dims[2]); - vtkm::Vec xyz = (queryCoord - Min) / Dxdydz; + vtkm::Vec xyz = (queryPoint - Min) / Dxdydz; float min_distance = std::numeric_limits::max(); vtkm::Id neareast = -1; @@ -138,11 +148,11 @@ public: auto upper = cellUpper.Get(cellid); for (auto index = lower; index < upper; index++) { - auto pointid = pointId.Get(index); - auto point = coordi_Handle.Get(pointid); - auto dx = point[0] - queryCoord[0]; - auto dy = point[1] - queryCoord[1]; - auto dz = point[2] - queryCoord[2]; + auto pointid = pointIds.Get(index); + auto point = coords.Get(pointid); + auto dx = point[0] - queryPoint[0]; + auto dy = point[1] - queryPoint[1]; + auto dz = point[2] - queryPoint[2]; auto distance2 = dx * dx + dy * dy + dz * dz; if (distance2 < min_distance) @@ -158,14 +168,21 @@ public: } } - nnId = neareast; - nnDis = vtkm::Sqrt(min_distance); + nearestNeighborId = neareast; + distance = vtkm::Sqrt(min_distance); }; private: vtkm::Vec Min; vtkm::Vec Dims; vtkm::Vec Dxdydz; + + CoordPortalType coords; + + IdPortalType pointIds; + IdPortalType cellIds; + IdPortalType cellLower; + IdPortalType cellUpper; }; /// \brief Construct a 3D uniform grid for nearest neighbor search. @@ -173,7 +190,8 @@ public: /// \param coords An ArrayHandle of x, y, z coordinates of input points. /// \param device Tag for selecting device adapter template - void Build(const vtkm::cont::ArrayHandle>& coords, DeviceAdapter) + Locator Build(const vtkm::cont::ArrayHandle>& coords, + DeviceAdapter) { using Algorithm = vtkm::cont::DeviceAdapterAlgorithm; // generate unique id for each input point @@ -192,33 +210,15 @@ public: vtkm::cont::ArrayHandleCounting cell_ids_counting(0, 1, Dims[0] * Dims[1] * Dims[2]); Algorithm::UpperBounds(CellIds, cell_ids_counting, CellUpper); Algorithm::LowerBounds(CellIds, cell_ids_counting, CellLower); - }; - /// \brief Nearest neighbor search using a Uniform Grid - /// - /// Parallel search of nearesat neighbor for each point in the \c queryPoints in the set of - /// \c coords. Returns neareast neighbot in \c nearestNeighborIds and distances to nearest - /// neighbor in \c distances. - /// - /// \param coords Point coordinates for training dataset. - /// \param queryPoints Point coordinates to query for nearest neighbors. - /// \param nearestNeighborIds Neareast neighbor in the training dataset for each points in - /// the test set - /// \param distances Distance between query points and their nearest neighbors. - /// \param device Tag for selecting device adapter. - template - void FindNearestPoint(const vtkm::cont::ArrayHandle>& coords, - const vtkm::cont::ArrayHandle>& queryPoints, - vtkm::cont::ArrayHandle& nearestNeighborIds, - vtkm::cont::ArrayHandle& distances, - DeviceAdapter) - { - UniformGridSearch uniformGridSearch(Min, Max, Dims); - - vtkm::worklet::DispatcherMapField searchDispatcher( - uniformGridSearch); - searchDispatcher.Invoke( - queryPoints, coords, PointIds, CellLower, CellUpper, nearestNeighborIds, distances); + // TODO: lifetime of coords??? + return Locator(Min, + Max, + Dims, + coords.GetPortalConstControl(), + PointIds.GetPortalConstControl(), + CellLower.GetPortalConstControl(), + CellUpper.GetPortalConstControl()); }; private: diff --git a/vtkm/cont/testing/TestingPointLocatorUniformGrid.h b/vtkm/cont/testing/TestingPointLocatorUniformGrid.h index 77a38ba3a..df87fca03 100644 --- a/vtkm/cont/testing/TestingPointLocatorUniformGrid.h +++ b/vtkm/cont/testing/TestingPointLocatorUniformGrid.h @@ -75,6 +75,30 @@ public: } }; +class PointLocatorUniformGridWorklet : public vtkm::worklet::WorkletMapField +{ +public: + typedef void ControlSignature(FieldIn<> qcIn, + ExecObject locator, + FieldOut<> nnIdOut, + FieldOut<> nnDistOut); + + typedef void ExecutionSignature(_1, _2, _3, _4); + + VTKM_CONT + PointLocatorUniformGridWorklet() {} + + // TODO: change IdType, it is used for other purpose. + template + VTKM_EXEC void operator()(const CoordiVecType& qc, + const Locator& locator, + IdType& nnIdOut, + CoordiType& nnDis) const + { + locator.FindNearestPoint(qc, nnIdOut, nnDis); + }; +}; + template class TestingPointLocatorUniformGrid { @@ -97,10 +121,11 @@ public: } auto coordi_Handle = vtkm::cont::make_ArrayHandle(coordi); - vtkm::worklet::PointLocatorUniformGrid uniformGrid( + vtkm::cont::PointLocatorUniformGrid uniformGrid( { 0.0f, 0.0f, 0.0f }, { 10.0f, 10.0f, 10.0f }, { 5, 5, 5 }); - uniformGrid.Build(coordi_Handle, VTKM_DEFAULT_DEVICE_ADAPTER_TAG()); + auto locator = uniformGrid.Build(coordi_Handle, VTKM_DEFAULT_DEVICE_ADAPTER_TAG()); + ///// randomly generate training points///// std::vector> qcVec; for (vtkm::Int32 i = 0; i < nTestingPoint; i++) { @@ -111,9 +136,12 @@ public: vtkm::cont::ArrayHandle nnId_Handle; vtkm::cont::ArrayHandle nnDis_Handle; - uniformGrid.FindNearestPoint( - coordi_Handle, qc_Handle, nnId_Handle, nnDis_Handle, VTKM_DEFAULT_DEVICE_ADAPTER_TAG()); + PointLocatorUniformGridWorklet pointLocatorUniformGridWorklet; + vtkm::worklet::DispatcherMapField locatorDispatcher( + pointLocatorUniformGridWorklet); + locatorDispatcher.Invoke(qc_Handle, locator, nnId_Handle, nnDis_Handle); + // brute force vtkm::cont::ArrayHandle bfnnId_Handle; vtkm::cont::ArrayHandle bfnnDis_Handle; NearestNeighborSearchBruteForce3DWorklet nnsbf3dWorklet; From 89c30aefddf067b44f53b1362aaebfd9f8c23e1e Mon Sep 17 00:00:00 2001 From: Li-Ta Lo Date: Thu, 3 May 2018 17:19:50 -0600 Subject: [PATCH 3/3] extract PrepareForExecution() as per Ken's feedback --- vtkm/cont/PointLocatorUniformGrid.h | 22 +++++++++++++------ .../testing/TestingPointLocatorUniformGrid.h | 3 ++- 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/vtkm/cont/PointLocatorUniformGrid.h b/vtkm/cont/PointLocatorUniformGrid.h index 90c75b213..e1deadb10 100644 --- a/vtkm/cont/PointLocatorUniformGrid.h +++ b/vtkm/cont/PointLocatorUniformGrid.h @@ -190,10 +190,13 @@ public: /// \param coords An ArrayHandle of x, y, z coordinates of input points. /// \param device Tag for selecting device adapter template - Locator Build(const vtkm::cont::ArrayHandle>& coords, - DeviceAdapter) + void Build(const vtkm::cont::ArrayHandle>& coords, DeviceAdapter) { using Algorithm = vtkm::cont::DeviceAdapterAlgorithm; + + // Save training data points. + Algorithm::Copy(coords, Coords); + // generate unique id for each input point vtkm::cont::ArrayHandleCounting pointCounting(0, 1, coords.GetNumberOfValues()); Algorithm::Copy(pointCounting, PointIds); @@ -210,22 +213,27 @@ public: vtkm::cont::ArrayHandleCounting cell_ids_counting(0, 1, Dims[0] * Dims[1] * Dims[2]); Algorithm::UpperBounds(CellIds, cell_ids_counting, CellUpper); Algorithm::LowerBounds(CellIds, cell_ids_counting, CellLower); + }; + template + Locator PrepareForExecution(DeviceAdapter) + { // TODO: lifetime of coords??? return Locator(Min, Max, Dims, - coords.GetPortalConstControl(), - PointIds.GetPortalConstControl(), - CellLower.GetPortalConstControl(), - CellUpper.GetPortalConstControl()); - }; + Coords.PrepareForInput(DeviceAdapter()), + PointIds.PrepareForInput(DeviceAdapter()), + CellLower.PrepareForInput(DeviceAdapter()), + CellUpper.PrepareForInput(DeviceAdapter())); + } private: vtkm::Vec Min; vtkm::Vec Max; vtkm::Vec Dims; + vtkm::cont::ArrayHandle> Coords; vtkm::cont::ArrayHandle PointIds; vtkm::cont::ArrayHandle CellIds; vtkm::cont::ArrayHandle CellLower; diff --git a/vtkm/cont/testing/TestingPointLocatorUniformGrid.h b/vtkm/cont/testing/TestingPointLocatorUniformGrid.h index df87fca03..13db92ec6 100644 --- a/vtkm/cont/testing/TestingPointLocatorUniformGrid.h +++ b/vtkm/cont/testing/TestingPointLocatorUniformGrid.h @@ -123,7 +123,8 @@ public: vtkm::cont::PointLocatorUniformGrid uniformGrid( { 0.0f, 0.0f, 0.0f }, { 10.0f, 10.0f, 10.0f }, { 5, 5, 5 }); - auto locator = uniformGrid.Build(coordi_Handle, VTKM_DEFAULT_DEVICE_ADAPTER_TAG()); + uniformGrid.Build(coordi_Handle, VTKM_DEFAULT_DEVICE_ADAPTER_TAG()); + auto locator = uniformGrid.PrepareForExecution(VTKM_DEFAULT_DEVICE_ADAPTER_TAG()); ///// randomly generate training points///// std::vector> qcVec;