Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce multipoint_range interface; Refactors point_distance API to support multipoint to multipoint distance. #731

Merged
merged 20 commits into from
Oct 19, 2022
Merged
Show file tree
Hide file tree
Changes from 19 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions cpp/benchmarks/points_in_range.cu
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,11 @@
* limitations under the License.
*/

#include "cuspatial/error.hpp"
#include <benchmarks/fixture/rmm_pool_raii.hpp>
#include <benchmarks/utility/random.cuh>
#include <cuspatial_test/random.cuh>

#include <cuspatial/detail/iterator.hpp>
#include <cuspatial/error.hpp>
#include <cuspatial/experimental/points_in_range.cuh>
#include <cuspatial/vec_2d.hpp>

Expand Down
23 changes: 13 additions & 10 deletions cpp/include/cuspatial/distance/point_distance.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,20 +22,23 @@ namespace cuspatial {

/**
* @ingroup distance
* @brief Compute pairwise point-to-point Cartesian distance
* @brief Compute pairwise (multi)point-to-(multi)point Cartesian distance
*
* @param points1_x Column of x-coordinates of the first point in each pair
* @param points1_y Column of y-coordinates of the first point in each pair
* @param points2_x Column of x-coordinates of the second point in each pair
* @param points2_y Column of y-coordinates of the second point in each pair
* @param stream The CUDA stream to use for device memory operations and kernel launches
* Computes the cartesian distance between each pair of the multipoints. If input is
* a single point column, the offset of the column should be std::nullopt.
*
isVoid marked this conversation as resolved.
Show resolved Hide resolved
* @param points1_xy Column of xy-coordinates of the first point in each pair
* @param multipoints1_offset Index to the first point of each multipoint in points1_xy
* @param points2_xy Column of xy-coordinates of the second point in each pair
* @param multipoints2_offset Index to the second point of each multipoint in points2_xy
* @return Column of distances between each pair of input points
*/

std::unique_ptr<cudf::column> pairwise_point_distance(
cudf::column_view const& points1_x,
cudf::column_view const& points1_y,
cudf::column_view const& points2_x,
cudf::column_view const& points2_y,
cudf::column_view const& points1_xy,
std::optional<cudf::device_span<cudf::size_type const>> multipoints1_offset,
cudf::column_view const& points2_xy,
std::optional<cudf::device_span<cudf::size_type const>> multipoints2_offset,
rmm::mr::device_memory_resource* mr = rmm::mr::get_current_device_resource());

} // namespace cuspatial
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*
* Copyright (c) 2022, NVIDIA CORPORATION.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <cuspatial/cuda_utils.hpp>

namespace cuspatial {
namespace geometry_collection {

template <typename VecIterator>
CUSPATIAL_HOST_DEVICE multipoint_ref<VecIterator>::multipoint_ref(VecIterator begin,
VecIterator end)
: _points_begin(begin), _points_end(end)
{
}

template <typename VecIterator>
CUSPATIAL_HOST_DEVICE auto multipoint_ref<VecIterator>::point_begin() const
{
return _points_begin;
}

template <typename VecIterator>
CUSPATIAL_HOST_DEVICE auto multipoint_ref<VecIterator>::point_end() const
{
return _points_end;
}

} // namespace geometry_collection
} // namespace cuspatial
41 changes: 24 additions & 17 deletions cpp/include/cuspatial/experimental/detail/point_distance.cuh
Original file line number Diff line number Diff line change
Expand Up @@ -29,33 +29,40 @@

namespace cuspatial {

template <class Cart2dItA, class Cart2dItB, class OutputIt>
OutputIt pairwise_point_distance(Cart2dItA points1_first,
Cart2dItA points1_last,
Cart2dItB points2_first,
template <class MultiPointArrayViewA, class MultiPointArrayViewB, class OutputIt>
OutputIt pairwise_point_distance(MultiPointArrayViewA multipoints1,
MultiPointArrayViewB multipoints2,
OutputIt distances_first,
rmm::cuda_stream_view stream)
{
using T = typename cuspatial::iterator_vec_base_type<Cart2dItA>;
using T = iterator_vec_base_type<typename MultiPointArrayViewA::point_it_t>;

static_assert(is_same_floating_point<T,
typename cuspatial::iterator_vec_base_type<Cart2dItB>,
typename cuspatial::iterator_value_type<OutputIt>>(),
"Inputs and output must have the same floating point value type.");
static_assert(
is_same_floating_point<T, iterator_vec_base_type<typename MultiPointArrayViewB::point_it_t>>(),
"Inputs must have the same floating point value type.");

static_assert(is_same<vec_2d<T>,
typename cuspatial::iterator_value_type<Cart2dItA>,
typename cuspatial::iterator_value_type<Cart2dItB>>(),
typename MultiPointArrayViewA::point_t,
typename MultiPointArrayViewB::point_t>(),
"All Input types must be cuspatial::vec_2d with the same value type");

CUSPATIAL_EXPECTS(multipoints1.size() == multipoints2.size(),
"Inputs should have the same number of multipoints.");

return thrust::transform(rmm::exec_policy(stream),
points1_first,
points1_last,
points2_first,
multipoints1.multipoint_begin(),
multipoints1.multipoint_end(),
multipoints2.multipoint_begin(),
distances_first,
[] __device__(auto p1, auto p2) {
auto v = p1 - p2;
return std::sqrt(dot(v, v));
[] __device__(auto& mp1, auto& mp2) {
T min_distance_squared = std::numeric_limits<T>::max();
for (vec_2d<T> const& p1 : mp1) {
for (vec_2d<T> const& p2 : mp2) {
auto v = p1 - p2;
min_distance_squared = min(min_distance_squared, dot(v, v));
}
}
return sqrt(min_distance_squared);
});
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
/*
* Copyright (c) 2022, NVIDIA CORPORATION.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#pragma once

#include <thrust/binary_search.h>
#include <thrust/distance.h>
#include <thrust/iterator/transform_iterator.h>
#include <thrust/pair.h>

#include <cuspatial/cuda_utils.hpp>
#include <cuspatial/detail/iterator.hpp>
#include <cuspatial/experimental/geometry_collection/multipoint_ref.cuh>
#include <cuspatial/traits.hpp>
#include <cuspatial/vec_2d.hpp>

namespace cuspatial {

using namespace cuspatial::detail;

namespace detail {
template <typename GeometryIterator, typename VecIterator>
struct to_multipoint_functor {
using difference_type = typename thrust::iterator_difference<GeometryIterator>::type;
GeometryIterator _offset_iter;
VecIterator _points_begin;

to_multipoint_functor(GeometryIterator offset_iter, VecIterator points_begin)
: _offset_iter(offset_iter), _points_begin(points_begin)
{
}

CUSPATIAL_HOST_DEVICE
auto operator()(difference_type const& i)
{
return geometry_collection::multipoint_ref<VecIterator>{_points_begin + _offset_iter[i],
_points_begin + _offset_iter[i + 1]};
}
};

} // namespace detail

template <typename GeometryIterator, typename VecIterator>
multipoint_range<GeometryIterator, VecIterator>::multipoint_range(GeometryIterator geometry_begin,
GeometryIterator geometry_end,
VecIterator points_begin,
VecIterator points_end)
: _geometry_begin(geometry_begin),
_geometry_end(geometry_end),
_points_begin(points_begin),
_points_end(points_end)
{
}

template <typename GeometryIterator, typename VecIterator>
auto multipoint_range<GeometryIterator, VecIterator>::size()
{
return thrust::distance(_geometry_begin, _geometry_end) - 1;
}

template <typename GeometryIterator, typename VecIterator>
auto multipoint_range<GeometryIterator, VecIterator>::multipoint_begin()
{
return cuspatial::detail::make_counting_transform_iterator(
0, detail::to_multipoint_functor(_geometry_begin, _points_begin));
}

template <typename GeometryIterator, typename VecIterator>
auto multipoint_range<GeometryIterator, VecIterator>::multipoint_end()
{
return multipoint_begin() + size();
}

template <typename GeometryIterator, typename VecIterator>
auto multipoint_range<GeometryIterator, VecIterator>::point_begin()
{
return _points_begin;
}

template <typename GeometryIterator, typename VecIterator>
auto multipoint_range<GeometryIterator, VecIterator>::point_end()
{
return _points_end;
}

template <typename GeometryIterator, typename VecIterator>
template <typename IndexType>
CUSPATIAL_HOST_DEVICE auto multipoint_range<GeometryIterator, VecIterator>::operator[](
IndexType idx)
{
return multipoint_begin()[idx];
}

} // namespace cuspatial
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*
* Copyright (c) 2022, NVIDIA CORPORATION.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <cuspatial/cuda_utils.hpp>

namespace cuspatial {
namespace geometry_collection {

/**
* @brief Represent a multipoint stored in structure of array on memory.
*
* @tparam VecIterator type of iterator to the underlying point array.
*/
template <typename VecIterator>
class multipoint_ref {
public:
CUSPATIAL_HOST_DEVICE multipoint_ref(VecIterator begin, VecIterator end);

/// Return iterator to the starting point of the multipoint.
CUSPATIAL_HOST_DEVICE auto point_begin() const;
/// Return iterator to one-past the last point of the multipoint.
CUSPATIAL_HOST_DEVICE auto point_end() const;

/// Return iterator to the starting point of the multipoint.
CUSPATIAL_HOST_DEVICE auto begin() const { return point_begin(); }
/// Return iterator the the one-past the last point of the multipoint.
CUSPATIAL_HOST_DEVICE auto end() const { return point_end(); }

protected:
VecIterator _points_begin;
VecIterator _points_end;
};
} // namespace geometry_collection
} // namespace cuspatial

#include <cuspatial/experimental/detail/geometry_collection/multipoint_ref.cuh>
32 changes: 8 additions & 24 deletions cpp/include/cuspatial/experimental/point_distance.cuh
Original file line number Diff line number Diff line change
Expand Up @@ -24,34 +24,18 @@ namespace cuspatial {
* @ingroup distance
* @copybrief cuspatial::pairwise_point_distance
*
* @tparam Cart2dItA iterator type for point array of the first point of each pair. Must meet
* the requirements of [LegacyRandomAccessIterator][LinkLRAI] and be device-accessible.
* @tparam Cart2dItB iterator type for point array of the second point of each pair. Must meet
* the requirements of [LegacyRandomAccessIterator][LinkLRAI] and be device-accessible.
* @tparam OutputIt iterator type for output array. Must meet the requirements of
* [LegacyRandomAccessIterator][LinkLRAI], be mutable and be device-accessible.
* @tparam MultiPointArrayViewA An instance of template type `array_view::multipoint_array`
* @tparam MultiPointArrayViewB An instance of template type `array_view::multipoint_array`
*
* @param points1_first beginning of range of the first point of each pair
* @param points1_last end of range of the first point of each pair
* @param points2_first beginning of range of the second point of each pair
* @param distances_first beginning iterator to output
* @param stream The CUDA stream to use for device memory operations and kernel launches
* @return Output iterator to one past the last element in the output range
*
* @pre all input iterators for coordinates must have a `value_type` of `cuspatial::vec_2d`.
* @pre all scalar types must be floating point types, and must be the same type for all input
* iterators and output iterators.
*
* [LinkLRAI]: https://en.cppreference.com/w/cpp/named_req/RandomAccessIterator
* "LegacyRandomAccessIterator"
* @param multipoints1 Range of first multipoint in each distance pair.
* @param multipoints2 Range of second multipoint in each distance pair.
* @return Iterator past the last distance computed
*/
template <class Cart2dItA, class Cart2dItB, class OutputIt>
OutputIt pairwise_point_distance(Cart2dItA points1_first,
Cart2dItA points1_last,
Cart2dItB points2_first,
template <class MultiPointArrayViewA, class MultiPointArrayViewB, class OutputIt>
OutputIt pairwise_point_distance(MultiPointArrayViewA multipoints1,
MultiPointArrayViewB multipoints2,
OutputIt distances_first,
rmm::cuda_stream_view stream = rmm::cuda_stream_default);

} // namespace cuspatial

#include <cuspatial/experimental/detail/point_distance.cuh>
Loading