-
Notifications
You must be signed in to change notification settings - Fork 245
Description
Summary
RMM's cccl_async_resource_ref wrapper defines an unconstrained friend get_property template that becomes ambiguous with CCCL's new default get_property for dynamic_accessibility_property. This breaks downstream consumers (e.g. raft) that use cuda::forward_property with rmm::device_async_resource_ref as the upstream type.
The CCCL nightly build failure is here: https://github.com/NVIDIA/cccl/actions/runs/23279043739/job/67688181940
Root Cause
CCCL main added dynamic_accessibility_property support (NVIDIA/cccl#7727), which introduces two new get_property overloads:
forward_property::__fn(line ~128 ofget_property.h): a friend that forwardsdynamic_accessibility_propertytoupstream_resource()via an unqualified call toget_property.cuda::mr::get_property(line ~191 ofget_property.h): a default implementation that infers accessibility from static properties.
When the upstream type is rmm::device_async_resource_ref (i.e. rmm::detail::cccl_async_resource_ref<resource_ref<device_accessible>>), the unqualified forwarding call finds two equally-viable candidates via ADL:
rmm::detail::get_property(cccl_async_resource_ref const&, Property)— unconstrained friend template at line 353 ofcccl_adaptors.hppcuda::mr::get_property(const _Resource&, dynamic_accessibility_property)— the CCCL default
Neither is more specialized than the other, so the compiler rejects the call as ambiguous.
Minimal Reproducer
Godbolt: https://godbolt.org/z/6exqE6Kv6
The following reproducer depends only on CCCL headers (no RMM headers needed). Build with:
nvcc -std=c++20 -x cu get_property_repro.cpp \
-I<cccl>/libcudacxx/include \
-I<cccl>/cub \
-I<cccl>/thrust/thrust/cmake/../..#include <cuda/memory_resource>
// Mock of rmm::device_async_resource_ref.
// The only detail that matters: a wrapper in a non-cuda::mr namespace
// with an unconstrained friend get_property template.
namespace mock_rmm::detail {
template <typename ResourceType>
class cccl_async_resource_ref {
public:
cccl_async_resource_ref() = default;
explicit cccl_async_resource_ref(ResourceType ref) : ref_{ref} {}
template <typename Property>
friend auto constexpr get_property(cccl_async_resource_ref const& r, Property p) noexcept
-> decltype(get_property(std::declval<ResourceType const&>(), p))
{
return get_property(r.ref_, p);
}
private:
ResourceType ref_;
};
} // namespace mock_rmm::detail
using mock_device_async_resource_ref =
mock_rmm::detail::cccl_async_resource_ref<cuda::mr::resource_ref<cuda::mr::device_accessible>>;
// Adaptor using cuda::forward_property with the mock upstream.
struct adaptor : cuda::forward_property<adaptor, mock_device_async_resource_ref> {
explicit adaptor(mock_device_async_resource_ref upstream) : upstream_{upstream} {}
mock_device_async_resource_ref upstream_resource() const { return upstream_; }
void* allocate(::cuda::stream_ref, std::size_t, std::size_t) { return nullptr; }
void deallocate(::cuda::stream_ref, void*, std::size_t, std::size_t) noexcept {}
void* allocate_sync(std::size_t, std::size_t) { return nullptr; }
void deallocate_sync(void*, std::size_t, std::size_t) noexcept {}
friend bool operator==(adaptor const&, adaptor const&) { return false; }
private:
mock_device_async_resource_ref upstream_;
};
// Type-erasing `adaptor` into resource_ref triggers the ambiguity.
template <typename T>
void trigger(T& resource)
{
cuda::mr::resource_ref<cuda::mr::device_accessible> erased{resource};
(void)erased;
}
template void trigger<adaptor>(adaptor&);Compiler Output (nvcc 13.0, CCCL main)
get_property.h(128): error: more than one instance of "get_property" matches the argument list:
function template "auto mock_rmm::detail::get_property(..., Property)" (line 46)
function template "cuda::mr::get_property(const _Resource &, dynamic_accessibility_property)" (line 191)
argument types are: (mock_device_async_resource_ref, dynamic_accessibility_property)
Possible Fixes
We must resolve #2011 fully, and #2301 in particular, to fix the root cause of this problem.
There may be a workaround where we constrain the friend get_property in RMM's cccl_async_resource_ref to exclude dynamic_accessibility_property (or any property that already has a more-specific overload in cuda::mr), e.g.:
template <typename Property,
std::enable_if_t<!std::is_same_v<Property, cuda::mr::dynamic_accessibility_property>>* = nullptr>
friend auto constexpr get_property(cccl_async_resource_ref const& r, Property p) noexcept
-> decltype(get_property(std::declval<ResourceType const&>(), p))
{
return get_property(r.ref_, p);
}Metadata
Metadata
Assignees
Labels
Type
Projects
Status