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

Refactor haversine_distance to a header-only API #477

Merged
merged 31 commits into from
Apr 28, 2022

Conversation

harrism
Copy link
Member

@harrism harrism commented Jan 19, 2022

This is an exploration of what a refactoring of libcuspatial to a header-only API would look like. This PR refactors a single API, haversine_distance. The new API is iterator-based, and is completely independent of libcudf and libcudf_test.

The design is based on std/Thrust algorithms. It is an iterator-based API, which enables flexibility to use "fancy" iterators such as transform iterators.

There is no support for nulls. We didn't allow cudf::column inputs with NULLS in the cuDF-based API anyway.

@github-actions github-actions bot added cmake Related to CMake code or build configuration libcuspatial Relates to the cuSpatial C++ library labels Jan 19, 2022
@harrism harrism added breaking Breaking change improvement Improvement / enhancement to an existing function labels Jan 19, 2022
@harrism harrism added this to PR-WIP in cuSpatial v22.04 Release via automation Jan 19, 2022
@harrism harrism added the 5 - DO NOT MERGE Hold off on merging; see PR for details label Jan 19, 2022
@@ -0,0 +1,125 @@
/*
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this be named haversine.cuh?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Depends on your style. Thrust doesn't follow that convention.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, in the future we may want to enable both host and device execution of these algorithms, a la Thrust.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought anything with CUDA C++ in it was supposed to either be .cu or .cuh? If someone includes this from a .cpp file, GCC won't know what to do with the __device__ functions?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

True. Thrust uses .h for all headers, and makes sure to protect everything so that it can be portable to different backends. I don't know if we want to go that direction. I just have a particular aversion to ".cuh" used in non-detail headers (not sure why, it's just ugly I guess).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Generally my rule is that .h/.hpp files should be able to included in a host-only TU without issue.

I'd go with .cuh unless we decide to make cuSpatial work on both CPU/GPU via Thrust.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. It would be nice to support CPU and GPU backends but I'm not sure how feasible that is with the more complicated algorithms. Also it would have a large impact on tests, which currently use device vectors. So this is definitely future work.

Copy link
Contributor

@jrhemstad jrhemstad left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this is experimenting with a new API/library design, some bigger pictures things to consider:

Do we want to provide per-algorithm control over the temporary allocations like Thrust? Or will cuSpatial continue to depend on RMM and a user can control temp allocations via per_device_resource?

Looking at the implementation, this algorithm could conceivably run on CPUs with the thrust::host backend. Is cuSpatial interested in providing the flexibility to run on both CPU and GPU?

@harrism
Copy link
Member Author

harrism commented Jan 19, 2022

Do we want to provide per-algorithm control over the temporary allocations like Thrust? Or will cuSpatial continue to depend on RMM and a user can control temp allocations via per_device_resource?

yeah, this is what I meant when I asked you if you thought it should take an exec policy argument. This algorithm doesn't allocate, so I removed the MR argument. But if it did, it could get the allocator from the exec_policy like Thrust does.

@harrism
Copy link
Member Author

harrism commented Jan 19, 2022

Looking at the implementation, this algorithm could conceivably run on CPUs with the thrust::host backend. Is cuSpatial interested in providing the flexibility to run on both CPU and GPU?

That requires further discussion. We have not received any requirements for this yet that I know of.

@harrism
Copy link
Member Author

harrism commented Apr 7, 2022

I made a significant changed based on my experimentation with refactoring other APIs which use both LonLat and XY coordinates. I replaced location_2d with a more generic vec_2d with x and y members. This can be used for both LonLat and XY which reduces code duplication especially in type utilities and arithmetic operators.

Copy link
Contributor

@isVoid isVoid left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm. 3 small nits in doc.

cpp/doc/libcuspatial_refactoring_guide.md Outdated Show resolved Hide resolved
cpp/doc/libcuspatial_refactoring_guide.md Outdated Show resolved Hide resolved
cpp/doc/libcuspatial_refactoring_guide.md Outdated Show resolved Hide resolved
Copy link
Contributor

@vyasr vyasr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CMake approval

cuSpatial v22.06 Release automation moved this from PR-WIP to PR-Reviewer approved Apr 27, 2022
Comment on lines 50 to 51
3. Longitude/Latitude data is passed as array of structures, using the `cuspatial::lonlat_2d`
type (include/cuspatial/types.hpp)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The code doesn't currently tell me this. Maybe add a static_assert to demonstrate it.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Concepts would be so nice for this :(

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand, I already have that static assert.

static_assert(
    std::conjunction_v<std::is_same<lonlat_2d<T>, Location>, std::is_same<lonlat_2d<T>, LocationB>>,
    "Inputs must be cuspatial::lonlat_2d");

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mentioned the static asserts in the refactoring guide.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reading the code on lines33-43 and then reading on it describes the important things about this code...

"There are a few key points to notice...

Longitude/Latitude data is passed as array of structures, using the cuspatial::lonlat_2d type"

My only point is that it's impossible to "notice" this point just from the code as is on 33-43.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Got it. I added this clarification to that point:

 Longitude/Latitude data is passed as array of structures, using the `cuspatial::lonlat_2d`
     type (include/cuspatial/types.hpp). This is enforced using a `static_assert` in the function
     body (discussed later).

@harrism
Copy link
Member Author

harrism commented Apr 28, 2022

Thanks everyone for reviewing! @gpucibot merge

@harrism harrism added 5 - Ready to Merge Testing and reviews complete, ready to merge and removed 3 - Ready for Review Ready for review by team labels Apr 28, 2022
@harrism
Copy link
Member Author

harrism commented Apr 28, 2022

@gpucibot merge

@rapids-bot rapids-bot bot merged commit 1986a18 into rapidsai:branch-22.06 Apr 28, 2022
cuSpatial v22.06 Release automation moved this from PR-Reviewer approved to Done Apr 28, 2022
@harrism harrism added this to the header-only C++ API milestone May 12, 2022
rapids-bot bot pushed a commit that referenced this pull request Jun 1, 2022
Following #477, implements the header-only API for `cuspatial::lonlat_to_cartesian` and implements existing C++ API on top of it.

Follows the refactoring guide introduced in #477.

Note this branch is based on the branch for #477 so diff includes all changes from that PR as well. Once #477 is merged this PR will simplify a lot.

Authors:
  - Mark Harris (https://github.com/harrism)

Approvers:
  - Vyas Ramasubramani (https://github.com/vyasr)
  - Michael Wang (https://github.com/isVoid)

URL: #514
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
5 - Ready to Merge Testing and reviews complete, ready to merge cmake Related to CMake code or build configuration improvement Improvement / enhancement to an existing function libcuspatial Relates to the cuSpatial C++ library non-breaking Non-breaking change
Projects
No open projects
Development

Successfully merging this pull request may close these issues.

None yet

5 participants