Skip to content

Commit 885ac00

Browse files
committed
Ensure all execution policies are also environments
We want to be able to pass additional information to execution policies. We already settled on the sender & receiver approach with queries and key value pairs. This refactors the current approach to turn `__execution_policy_base` into a proper environment. That has the advantage that we do not need to handle the cuda execution policy in a special way. The only cuda specific code is when we want to ensure that streams are passed as `cuda::stream_ref` and memory resources as `cuda::mr::resource_ref`
1 parent 1075a2c commit 885ac00

File tree

14 files changed

+535
-288
lines changed

14 files changed

+535
-288
lines changed

libcudacxx/include/cuda/__execution/policy.h

Lines changed: 3 additions & 194 deletions
Original file line numberDiff line numberDiff line change
@@ -22,207 +22,16 @@
2222

2323
#if _CCCL_HAS_BACKEND_CUDA()
2424

25-
# include <cuda/__functional/call_or.h>
26-
# include <cuda/__fwd/execution_policy.h>
27-
# include <cuda/__memory_resource/any_resource.h>
28-
# include <cuda/__memory_resource/get_memory_resource.h>
29-
# include <cuda/__memory_resource/resource.h>
30-
# include <cuda/__stream/get_stream.h>
31-
# include <cuda/__stream/stream_ref.h>
3225
# include <cuda/std/__execution/policy.h>
33-
# include <cuda/std/__type_traits/is_execution_policy.h>
34-
# include <cuda/std/__utility/forward.h>
35-
# include <cuda/std/__utility/move.h>
3626

3727
# include <cuda/std/__cccl/prologue.h>
3828

39-
_CCCL_BEGIN_NAMESPACE_CUDA_STD_EXECUTION
40-
41-
template <bool _HasStream>
42-
struct __policy_stream_holder
43-
{
44-
::cuda::stream_ref __stream_;
45-
46-
_CCCL_HOST_API constexpr __policy_stream_holder(::cuda::stream_ref __stream) noexcept
47-
: __stream_(__stream)
48-
{}
49-
};
50-
51-
template <>
52-
struct __policy_stream_holder<false>
53-
{
54-
_CCCL_HIDE_FROM_ABI __policy_stream_holder() = default;
55-
56-
//! @brief Dummy constructor to simplify implementation of the cuda policy
57-
_CCCL_HOST_API constexpr __policy_stream_holder(::cuda::stream_ref) noexcept {}
58-
};
59-
60-
template <bool _HasResource>
61-
struct __policy_memory_resource_holder
62-
{
63-
::cuda::mr::resource_ref<::cuda::mr::device_accessible> __resource_;
64-
65-
_CCCL_HIDE_FROM_ABI __policy_memory_resource_holder() = default;
66-
67-
_CCCL_HOST_API constexpr __policy_memory_resource_holder(
68-
::cuda::mr::resource_ref<::cuda::mr::device_accessible> __resource) noexcept
69-
: __resource_(__resource)
70-
{}
71-
};
72-
73-
template <>
74-
struct __policy_memory_resource_holder<false>
75-
{
76-
_CCCL_HIDE_FROM_ABI __policy_memory_resource_holder() = default;
77-
78-
//! @brief Dummy constructor to simplify implementation of the cuda policy
79-
_CCCL_HOST_API constexpr __policy_memory_resource_holder(
80-
::cuda::mr::resource_ref<::cuda::mr::device_accessible>) noexcept
81-
{}
82-
};
83-
84-
template <uint32_t _Policy>
85-
struct _CCCL_DECLSPEC_EMPTY_BASES __execution_policy_base<_Policy, __execution_backend::__cuda>
86-
: __execution_policy_base<_Policy, __execution_backend::__none>
87-
, protected __policy_stream_holder<__cuda_policy_with_stream<_Policy>>
88-
, protected __policy_memory_resource_holder<__cuda_policy_with_memory_resource<_Policy>>
89-
{
90-
private:
91-
template <uint32_t, __execution_backend>
92-
friend struct __execution_policy_base;
93-
94-
using __stream_holder = __policy_stream_holder<__cuda_policy_with_stream<_Policy>>;
95-
using __resource_holder = __policy_memory_resource_holder<__cuda_policy_with_memory_resource<_Policy>>;
96-
97-
_CCCL_TEMPLATE(bool _WithStream = __cuda_policy_with_stream<_Policy>,
98-
bool _WithResource = __cuda_policy_with_memory_resource<_Policy>)
99-
_CCCL_REQUIRES((_WithStream) _CCCL_AND(!_WithResource))
100-
_CCCL_HOST_API constexpr __execution_policy_base(::cuda::stream_ref __stream) noexcept
101-
: __stream_holder(__stream)
102-
, __resource_holder()
103-
{}
104-
105-
_CCCL_TEMPLATE(bool _WithStream = __cuda_policy_with_stream<_Policy>,
106-
bool _WithResource = __cuda_policy_with_memory_resource<_Policy>)
107-
_CCCL_REQUIRES((!_WithStream) _CCCL_AND _WithResource)
108-
_CCCL_HOST_API constexpr __execution_policy_base(
109-
::cuda::mr::resource_ref<::cuda::mr::device_accessible> __resource) noexcept
110-
: __stream_holder()
111-
, __resource_holder(::cuda::std::move(__resource)) // NVCC 12.0 needs the move
112-
{}
113-
114-
_CCCL_TEMPLATE(bool _WithStream = __cuda_policy_with_stream<_Policy>,
115-
bool _WithResource = __cuda_policy_with_memory_resource<_Policy>)
116-
_CCCL_REQUIRES(_WithStream _CCCL_AND _WithResource)
117-
_CCCL_HOST_API constexpr __execution_policy_base(
118-
::cuda::stream_ref __stream, ::cuda::mr::resource_ref<::cuda::mr::device_accessible> __resource) noexcept
119-
: __stream_holder(__stream)
120-
, __resource_holder(::cuda::std::move(__resource))
121-
{}
122-
123-
public:
124-
_CCCL_HIDE_FROM_ABI constexpr __execution_policy_base() noexcept = default;
125-
126-
//! @brief Convert to a policy that holds a stream
127-
//! @note This cannot be merged with the other case where we already have a stream as this needs to be const qualified
128-
//! This is because we start with a constexpr global and modify that through with
129-
[[nodiscard]] _CCCL_HOST_API auto with(const ::cuda::get_stream_t&, ::cuda::stream_ref __stream) const noexcept
130-
{
131-
constexpr uint32_t __new_policy = __set_cuda_backend_option<_Policy, __cuda_backend_options::__with_stream>;
132-
if constexpr (__cuda_policy_with_memory_resource<_Policy>)
133-
{
134-
return __execution_policy_base<__new_policy>{__stream, this->__resource_};
135-
}
136-
else
137-
{
138-
return __execution_policy_base<__new_policy>{__stream};
139-
}
140-
}
141-
142-
//! @brief Return the stream stored in the holder or a default stream
143-
_CCCL_TEMPLATE(bool _WithStream = __cuda_policy_with_stream<_Policy>)
144-
_CCCL_REQUIRES(_WithStream)
145-
[[nodiscard]] _CCCL_API ::cuda::stream_ref query(const ::cuda::get_stream_t&) const noexcept
146-
{
147-
return this->__stream_;
148-
}
149-
150-
//! @brief Convert to a policy that holds a memory resource
151-
//! @warning We hold the memory resource by reference, so passing rvalue is a bug
152-
template <class _Resource>
153-
[[nodiscard]] _CCCL_HOST_API auto with(const cuda::mr::get_memory_resource_t&, _Resource&&) const = delete;
154-
155-
//! @brief Convert to a policy that holds a memory resource
156-
//! @note This cannot be merged with the other case as this needs to be const qualified
157-
//! This is because we start with a constexpr global and modify that through with
158-
template <class _Resource>
159-
[[nodiscard]] _CCCL_HOST_API auto with(const cuda::mr::get_memory_resource_t&, _Resource& __resource) const noexcept
160-
{
161-
constexpr uint32_t __new_policy =
162-
__set_cuda_backend_option<_Policy, __cuda_backend_options::__with_memory_resource>;
163-
if constexpr (__cuda_policy_with_stream<_Policy>)
164-
{
165-
return __execution_policy_base<__new_policy>{this->__stream_, __resource};
166-
}
167-
else
168-
{
169-
return __execution_policy_base<__new_policy>{__resource};
170-
}
171-
}
172-
173-
//! @brief Return either a stored or a default memory resource
174-
_CCCL_TEMPLATE(bool _WithResource = __cuda_policy_with_memory_resource<_Policy>)
175-
_CCCL_REQUIRES(_WithResource)
176-
[[nodiscard]] _CCCL_API auto query(const ::cuda::mr::get_memory_resource_t&) const noexcept
177-
{
178-
return this->__resource_;
179-
}
180-
181-
template <uint32_t _OtherPolicy, __execution_backend _OtherBackend>
182-
[[nodiscard]] _CCCL_API friend constexpr bool operator==(
183-
const __execution_policy_base& __lhs, const __execution_policy_base<_OtherPolicy, _OtherBackend>& __rhs) noexcept
184-
{
185-
if constexpr (_Policy != _OtherPolicy)
186-
{
187-
return false;
188-
}
189-
190-
if constexpr (__cuda_policy_with_stream<_Policy>)
191-
{
192-
if (__lhs.query(::cuda::get_stream) != __rhs.query(::cuda::get_stream))
193-
{
194-
return false;
195-
}
196-
}
197-
198-
if constexpr (__cuda_policy_with_memory_resource<_Policy>)
199-
{
200-
if (__lhs.query(::cuda::mr::get_memory_resource) != __rhs.query(::cuda::mr::get_memory_resource))
201-
{
202-
return false;
203-
}
204-
}
205-
206-
return true;
207-
}
208-
209-
# if _CCCL_STD_VER <= 2017
210-
template <uint32_t _OtherPolicy, __execution_backend _OtherBackend>
211-
[[nodiscard]] _CCCL_API friend constexpr bool operator!=(
212-
const __execution_policy_base& __lhs, const __execution_policy_base<_OtherPolicy, _OtherBackend>& __rhs) noexcept
213-
{
214-
return !(__lhs == __rhs);
215-
}
216-
# endif // _CCCL_STD_VER <= 2017
217-
};
218-
219-
_CCCL_END_NAMESPACE_CUDA_STD_EXECUTION
220-
22129
_CCCL_BEGIN_NAMESPACE_CUDA_EXECUTION
22230

22331
using __cub_parallel_unsequenced_policy =
224-
::cuda::std::execution::__execution_policy_base<::cuda::std::execution::__with_cuda_backend<static_cast<uint32_t>(
225-
::cuda::std::execution::__execution_policy::__parallel_unsequenced)>()>;
32+
::cuda::std::execution::__execution_policy_base<::cuda::std::execution::__with_backend<
33+
static_cast<uint32_t>(::cuda::std::execution::__execution_policy::__parallel_unsequenced),
34+
::cuda::std::execution::__execution_backend::__cuda>()>;
22635
_CCCL_GLOBAL_CONSTANT __cub_parallel_unsequenced_policy __cub_par_unseq{};
22736

22837
_CCCL_END_NAMESPACE_CUDA_EXECUTION

libcudacxx/include/cuda/__fwd/execution_policy.h

Lines changed: 0 additions & 73 deletions
This file was deleted.
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// Part of libcu++, the C++ Standard Library for your entire system,
4+
// under the Apache License v2.0 with LLVM Exceptions.
5+
// See https://llvm.org/LICENSE.txt for license information.
6+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7+
// SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES.
8+
//
9+
//===----------------------------------------------------------------------===//
10+
11+
#ifndef _CUDA___FWD_GET_MEMORY_RESOURCE_H
12+
#define _CUDA___FWD_GET_MEMORY_RESOURCE_H
13+
14+
#include <cuda/std/detail/__config>
15+
16+
#if defined(_CCCL_IMPLICIT_SYSTEM_HEADER_GCC)
17+
# pragma GCC system_header
18+
#elif defined(_CCCL_IMPLICIT_SYSTEM_HEADER_CLANG)
19+
# pragma clang system_header
20+
#elif defined(_CCCL_IMPLICIT_SYSTEM_HEADER_MSVC)
21+
# pragma system_header
22+
#endif // no system header
23+
24+
#if _CCCL_HAS_CTK()
25+
26+
# include <cuda/std/__cccl/prologue.h>
27+
28+
_CCCL_BEGIN_NAMESPACE_CUDA_MR
29+
30+
struct __get_memory_resource_t;
31+
32+
_CCCL_END_NAMESPACE_CUDA_MR
33+
34+
# include <cuda/std/__cccl/epilogue.h>
35+
36+
#endif // _CCCL_HAS_CTK()
37+
38+
#endif // _CUDA___FWD_GET_MEMORY_RESOURCE_H

libcudacxx/include/cuda/__fwd/get_stream.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,4 +35,4 @@ _CCCL_END_NAMESPACE_CUDA
3535

3636
#endif // _CCCL_HAS_CTK()
3737

38-
#endif // _CUDA___FWD_PIPELINE_H
38+
#endif // _CUDA___FWD_GET_STREAM_H

libcudacxx/include/cuda/__memory_resource/any_resource.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -839,6 +839,12 @@ using resource_ref = basic_resource_ref<_ResourceKind::_Asynchronous, _Propertie
839839

840840
# endif // _CCCL_DOXYGEN_INVOKED
841841

842+
template <class _Tp>
843+
inline constexpr bool __is_resource_ref = false;
844+
845+
template <class... _Properties>
846+
inline constexpr bool __is_resource_ref<resource_ref<_Properties...>> = true;
847+
842848
//! @rst
843849
//! .. _libcudacxx-memory-resource-make-any-resource:
844850
//!

libcudacxx/include/cuda/__memory_resource/get_memory_resource.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323

2424
#if _CCCL_HAS_CTK()
2525

26+
# include <cuda/__fwd/get_memory_resource.h>
2627
# include <cuda/__memory_resource/properties.h>
2728
# include <cuda/__memory_resource/resource.h>
2829
# include <cuda/__stream/stream_ref.h>
@@ -35,8 +36,6 @@
3536

3637
_CCCL_BEGIN_NAMESPACE_CUDA_MR
3738

38-
struct __get_memory_resource_t;
39-
4039
template <class _Tp>
4140
_CCCL_CONCEPT __has_member_get_resource = _CCCL_REQUIRES_EXPR((_Tp), const _Tp& __t)(
4241
requires(resource<::cuda::std::remove_cvref_t<decltype(__t.get_memory_resource())>>));

0 commit comments

Comments
 (0)