Skip to content

Commit

Permalink
Refactor of pairwise_linestring_distance to use `multilinestring_ra…
Browse files Browse the repository at this point in the history
…nge`, adds support to multilinestring distance (#755)

Note, this is the first part of `pairwise_linestring_distance` refactoring, part 1 of PR: #753

Depends on #752 

Contributes to #706, #703

Closes #745

Authors:
  - Michael Wang (https://github.com/isVoid)

Approvers:
  - H. Thomson Comer (https://github.com/thomcom)
  - Mark Harris (https://github.com/harrism)

URL: #755
  • Loading branch information
isVoid authored Nov 7, 2022
1 parent 8702bc6 commit 870f103
Show file tree
Hide file tree
Showing 15 changed files with 1,300 additions and 333 deletions.
41 changes: 18 additions & 23 deletions cpp/benchmarks/pairwise_linestring_distance.cu
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include <cuspatial/detail/iterator.hpp>
#include <cuspatial/experimental/iterator_factory.cuh>
#include <cuspatial/experimental/linestring_distance.cuh>
#include <cuspatial/experimental/ranges/multilinestring_range.cuh>
#include <cuspatial/vec_2d.hpp>

#include <rmm/device_vector.hpp>
Expand Down Expand Up @@ -104,13 +105,21 @@ void pairwise_linestring_distance_benchmark(nvbench::state& state, nvbench::type
auto [ls2, ls2_offset] =
generate_linestring<T>(num_string_pairs, num_segments_per_string, 1, {100, 100});

auto ls1_offset_begin = ls1_offset.begin();
auto ls2_offset_begin = ls2_offset.begin();
auto ls1_points_begin = ls1.begin();
auto ls2_points_begin = ls2.begin();
auto distances = rmm::device_vector<T>(ls1.size());
auto out_it = distances.begin();

auto distances = rmm::device_vector<T>(ls1.size());
auto out_it = distances.begin();

auto multilinestrings1 = make_multilinestring_range(1,
thrust::make_counting_iterator(0),
num_string_pairs,
ls1_offset.begin(),
ls1.size(),
ls1.begin());
auto multilinestrings2 = make_multilinestring_range(1,
thrust::make_counting_iterator(0),
num_string_pairs,
ls2_offset.begin(),
ls2.size(),
ls2.begin());
auto const total_points = ls1.size() + ls2.size();

state.add_element_count(num_string_pairs, "LineStringPairs");
Expand All @@ -120,22 +129,8 @@ void pairwise_linestring_distance_benchmark(nvbench::state& state, nvbench::type
state.add_global_memory_writes<T>(num_string_pairs);

state.exec(nvbench::exec_tag::sync,
[&ls1_offset_begin,
&num_string_pairs,
&ls1_points_begin,
ls1_size = ls1.size(),
&ls2_offset_begin,
&ls2_points_begin,
ls2_size = ls2.size(),
&out_it](nvbench::launch& launch) {
pairwise_linestring_distance(ls1_offset_begin,
ls1_offset_begin + num_string_pairs,
ls1_points_begin,
ls1_points_begin + ls1_size,
ls2_offset_begin,
ls2_points_begin,
ls2_points_begin + ls2_size,
out_it);
[&multilinestrings1, &multilinestrings2, &out_it](nvbench::launch& launch) {
pairwise_linestring_distance(multilinestrings1, multilinestrings2, out_it);
});
}

Expand Down
7 changes: 3 additions & 4 deletions cpp/include/cuspatial/detail/iterator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,16 @@
*/

#pragma once

#include <cudf/types.hpp>
#include <cuspatial/cuda_utils.hpp>

#include <thrust/iterator/counting_iterator.h>
#include <thrust/iterator/transform_iterator.h>

namespace cuspatial {
namespace detail {

template <typename UnaryFunction>
inline auto make_counting_transform_iterator(cudf::size_type start, UnaryFunction f)
template <typename IndexType, typename UnaryFunction>
inline CUSPATIAL_HOST_DEVICE auto make_counting_transform_iterator(IndexType start, UnaryFunction f)
{
return thrust::make_transform_iterator(thrust::make_counting_iterator(start), f);
}
Expand Down
7 changes: 3 additions & 4 deletions cpp/include/cuspatial/detail/utility/linestring.cuh
Original file line number Diff line number Diff line change
Expand Up @@ -92,10 +92,9 @@ __forceinline__ T __device__ segment_distance_no_intersect_or_colinear(vec_2d<T>
vec_2d<T> const& c,
vec_2d<T> const& d)
{
auto dist_sqr = std::min(std::min(point_to_segment_distance_squared(a, c, d),
point_to_segment_distance_squared(b, c, d)),
std::min(point_to_segment_distance_squared(c, a, b),
point_to_segment_distance_squared(d, a, b)));
auto dist_sqr = min(
min(point_to_segment_distance_squared(a, c, d), point_to_segment_distance_squared(b, c, d)),
min(point_to_segment_distance_squared(c, a, b), point_to_segment_distance_squared(d, a, b)));
return dist_sqr;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/*
* 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>
#include <cuspatial/detail/iterator.hpp>
#include <cuspatial/traits.hpp>

#include <thrust/iterator/zip_iterator.h>
#include <thrust/tuple.h>

namespace cuspatial {

template <typename VecIterator>
struct to_segment_functor {
using element_t = iterator_vec_base_type<VecIterator>;
using difference_type = typename thrust::iterator_difference<VecIterator>::type;
VecIterator _point_begin;

CUSPATIAL_HOST_DEVICE
to_segment_functor(VecIterator point_begin) : _point_begin(point_begin) {}

CUSPATIAL_HOST_DEVICE
thrust::pair<vec_2d<element_t>, vec_2d<element_t>> operator()(difference_type i)
{
return {_point_begin[i], _point_begin[i + 1]};
}
};

template <typename VecIterator>
CUSPATIAL_HOST_DEVICE linestring_ref<VecIterator>::linestring_ref(VecIterator begin,
VecIterator end)
: _point_begin(begin), _point_end(end)
{
using T = iterator_vec_base_type<VecIterator>;
static_assert(is_same<vec_2d<T>, iterator_value_type<VecIterator>>(), "must be vec2d type");
}

template <typename VecIterator>
CUSPATIAL_HOST_DEVICE auto linestring_ref<VecIterator>::num_segments() const
{
// The number of segment equals the number of points minus 1. And the number of points
// is thrust::distance(_point_begin, _point_end) - 1.
return thrust::distance(_point_begin, _point_end) - 1;
}

template <typename VecIterator>
CUSPATIAL_HOST_DEVICE auto linestring_ref<VecIterator>::segment_begin() const
{
return detail::make_counting_transform_iterator(0, to_segment_functor{_point_begin});
}

template <typename VecIterator>
CUSPATIAL_HOST_DEVICE auto linestring_ref<VecIterator>::segment_end() const
{
return segment_begin() + num_segments();
}

} // namespace cuspatial
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
#pragma once

#include "cuspatial/cuda_utils.hpp"
#include <cuspatial/detail/iterator.hpp>
#include <cuspatial/experimental/geometry/linestring_ref.cuh>

#include <thrust/iterator/transform_iterator.h>

namespace cuspatial {

template <typename PartIterator, typename VecIterator>
struct to_linestring_functor {
using difference_type = typename thrust::iterator_difference<PartIterator>::type;
PartIterator part_begin;
VecIterator point_begin;

CUSPATIAL_HOST_DEVICE
to_linestring_functor(PartIterator part_begin, VecIterator point_begin)
: part_begin(part_begin), point_begin(point_begin)
{
}

CUSPATIAL_HOST_DEVICE auto operator()(difference_type i)
{
return linestring_ref{point_begin + part_begin[i], point_begin + part_begin[i + 1]};
}
};

template <typename PartIterator, typename VecIterator>
class multilinestring_ref;

template <typename PartIterator, typename VecIterator>
CUSPATIAL_HOST_DEVICE multilinestring_ref<PartIterator, VecIterator>::multilinestring_ref(
PartIterator part_begin, PartIterator part_end, VecIterator point_begin, VecIterator point_end)
: _part_begin(part_begin), _part_end(part_end), _point_begin(point_begin), _point_end(point_end)
{
}

template <typename PartIterator, typename VecIterator>
CUSPATIAL_HOST_DEVICE auto multilinestring_ref<PartIterator, VecIterator>::num_linestrings() const
{
return thrust::distance(_part_begin, _part_end) - 1;
}

template <typename PartIterator, typename VecIterator>
CUSPATIAL_HOST_DEVICE auto multilinestring_ref<PartIterator, VecIterator>::part_begin() const
{
return detail::make_counting_transform_iterator(0,
to_linestring_functor{_part_begin, _point_begin});
}

template <typename PartIterator, typename VecIterator>
CUSPATIAL_HOST_DEVICE auto multilinestring_ref<PartIterator, VecIterator>::part_end() const
{
return part_begin() + num_linestrings();
}

template <typename PartIterator, typename VecIterator>
CUSPATIAL_HOST_DEVICE auto multilinestring_ref<PartIterator, VecIterator>::point_begin() const
{
return _point_begin;
}

template <typename PartIterator, typename VecIterator>
CUSPATIAL_HOST_DEVICE auto multilinestring_ref<PartIterator, VecIterator>::point_end() const
{
return _point_end;
}

} // namespace cuspatial
Loading

0 comments on commit 870f103

Please sign in to comment.