Skip to content

Commit 48d307e

Browse files
authored
Add environment to encapsulate information needed for cudax::vector (NVIDIA#2775)
* Add a `get_memory_resource` CPO to query a type for a memory resource * Add query for execution policies * Implement an execution environment We need something that encapsulates the information we need for containers and algorithms, so start with a proper environment
1 parent dad9a33 commit 48d307e

File tree

21 files changed

+918
-71
lines changed

21 files changed

+918
-71
lines changed

cudax/include/cuda/experimental/__container/uninitialized_async_buffer.cuh

+1-1
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,7 @@ public:
250250
//! Returns a \c const reference to the :ref:`any_async_resource <cudax-memory-resource-any-async-resource>`
251251
//! that holds the memory resource used to allocate the buffer
252252
//! @endrst
253-
_CCCL_NODISCARD _CCCL_HIDE_FROM_ABI const __async_resource& get_resource() const noexcept
253+
_CCCL_NODISCARD _CCCL_HIDE_FROM_ABI const __async_resource& get_memory_resource() const noexcept
254254
{
255255
return __mr_;
256256
}

cudax/include/cuda/experimental/__container/uninitialized_buffer.cuh

+1-1
Original file line numberDiff line numberDiff line change
@@ -233,7 +233,7 @@ public:
233233
//! Returns a \c const reference to the :ref:`any_resource <cudax-memory-resource-any-resource>`
234234
//! that holds the memory resource used to allocate the buffer
235235
//! @endrst
236-
_CCCL_NODISCARD _CCCL_HIDE_FROM_ABI const __resource& get_resource() const noexcept
236+
_CCCL_NODISCARD _CCCL_HIDE_FROM_ABI const __resource& get_memory_resource() const noexcept
237237
{
238238
return __mr_;
239239
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// Part of CUDA Experimental in CUDA C++ Core Libraries,
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) 2024 NVIDIA CORPORATION & AFFILIATES.
8+
//
9+
//===----------------------------------------------------------------------===//
10+
11+
#ifndef __CUDAX___EXECUTION_ENV_CUH
12+
#define __CUDAX___EXECUTION_ENV_CUH
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+
#include <cuda/__memory_resource/properties.h>
25+
#include <cuda/std/__type_traits/is_same.h>
26+
#include <cuda/std/__utility/forward.h>
27+
#include <cuda/std/__utility/move.h>
28+
29+
#include <cuda/experimental/__async/sender/queries.cuh>
30+
#include <cuda/experimental/__execution/policy.cuh>
31+
#include <cuda/experimental/__memory_resource/any_resource.cuh>
32+
#include <cuda/experimental/__memory_resource/device_memory_resource.cuh>
33+
#include <cuda/experimental/__memory_resource/get_memory_resource.cuh>
34+
#include <cuda/experimental/__stream/get_stream.cuh>
35+
#include <cuda/experimental/__stream/stream_ref.cuh>
36+
37+
namespace cuda::experimental
38+
{
39+
40+
template <class... _Properties>
41+
class env_t
42+
{
43+
private:
44+
using __resource = any_async_resource<_Properties...>;
45+
using __stream_ref = stream_ref;
46+
47+
__resource __mr_ = device_memory_resource{};
48+
__stream_ref __stream_ = detail::__invalid_stream;
49+
execution::execution_policy __policy_ = execution::execution_policy::invalid_execution_policy;
50+
51+
public:
52+
//! @brief Default constructs an environment using ``device_memory_resource`` as the resource the default stream
53+
//! ``execution_policy::invalid_execution_policy`` as the execution policy
54+
_CCCL_HIDE_FROM_ABI env_t() = default;
55+
56+
//! @brief Construct an env_t from an any_resource, a stream and a policy
57+
//! @param __mr The any_resource passed in
58+
//! @param __stream The stream_ref passed in
59+
//! @param __policy The execution_policy passed in
60+
_CCCL_HIDE_FROM_ABI
61+
env_t(__resource __mr,
62+
__stream_ref __stream = detail::__invalid_stream,
63+
execution::execution_policy __policy = execution::execution_policy::invalid_execution_policy) noexcept
64+
: __mr_(_CUDA_VSTD::move(__mr))
65+
, __stream_(__stream)
66+
, __policy_(__policy)
67+
{}
68+
69+
//! @brief Checks whether another env is compatible with this one. That requires it to have queries for the three
70+
//! properties we need
71+
template <class _Env>
72+
static constexpr bool __is_compatible_env =
73+
__async::__queryable<_Env, get_memory_resource_t> && __async::__queryable<_Env, get_stream_t>
74+
&& __async::__queryable<_Env, execution::get_execution_policy_t>;
75+
76+
//! @brief Construct from an environment that has the right queries
77+
//! @param __env The environment we are querying for the required information
78+
_CCCL_TEMPLATE(class _Env)
79+
_CCCL_REQUIRES((!_CCCL_TRAIT(_CUDA_VSTD::is_same, _Env, env_t)) _CCCL_AND __is_compatible_env<_Env>)
80+
_CCCL_HIDE_FROM_ABI env_t(const _Env& __env) noexcept
81+
: __mr_(__env.query(get_memory_resource))
82+
, __stream_(__env.query(get_stream))
83+
, __policy_(__env.query(execution::get_execution_policy))
84+
{}
85+
86+
_CCCL_NODISCARD _CCCL_HIDE_FROM_ABI const __resource& query(get_memory_resource_t) const noexcept
87+
{
88+
return __mr_;
89+
}
90+
91+
_CCCL_NODISCARD _CCCL_HIDE_FROM_ABI __stream_ref query(get_stream_t) const noexcept
92+
{
93+
return __stream_;
94+
}
95+
96+
_CCCL_NODISCARD _CCCL_HIDE_FROM_ABI execution::execution_policy query(execution::get_execution_policy_t) const noexcept
97+
{
98+
return __policy_;
99+
}
100+
};
101+
102+
} // namespace cuda::experimental
103+
104+
#endif //__CUDAX___EXECUTION_ENV_CUH

cudax/include/cuda/experimental/__execution/policy.cuh

+38
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,18 @@
2121
# pragma system_header
2222
#endif // no system header
2323

24+
#include <cuda/std/__concepts/concept_macros.h>
25+
#include <cuda/std/__type_traits/is_convertible.h>
26+
27+
#include <cuda/experimental/__async/sender/queries.cuh>
2428
#include <cuda/experimental/__async/sender/utility.cuh>
2529

2630
namespace cuda::experimental::execution
2731
{
2832

2933
enum class execution_policy
3034
{
35+
invalid_execution_policy,
3136
sequenced_host,
3237
sequenced_device,
3338
parallel_host,
@@ -57,6 +62,39 @@ _CCCL_INLINE_VAR constexpr bool __is_unsequenced_execution_policy =
5762
_Policy == execution_policy::unsequenced_host || _Policy == execution_policy::unsequenced_device
5863
|| _Policy == execution_policy::parallel_unsequenced_host || _Policy == execution_policy::parallel_unsequenced_device;
5964

65+
struct get_execution_policy_t;
66+
67+
template <class _Tp>
68+
_CCCL_CONCEPT __has_member_get_execution_policy = _CCCL_REQUIRES_EXPR((_Tp), const _Tp& __t)(
69+
requires(_CCCL_TRAIT(_CUDA_VSTD::is_convertible, decltype(__t.get_execution_policy()), execution_policy)));
70+
71+
template <class _Env>
72+
_CCCL_CONCEPT __has_query_get_execution_policy = _CCCL_REQUIRES_EXPR((_Env))(
73+
requires(!__has_member_get_execution_policy<_Env>),
74+
requires(_CCCL_TRAIT(_CUDA_VSTD::is_convertible,
75+
::cuda::experimental::__async::__query_result_t<const _Env&, get_execution_policy_t>,
76+
execution_policy)));
77+
78+
struct get_execution_policy_t
79+
{
80+
_CCCL_TEMPLATE(class _Tp)
81+
_CCCL_REQUIRES(__has_member_get_execution_policy<_Tp>)
82+
_CCCL_NODISCARD _CCCL_HIDE_FROM_ABI execution_policy operator()(const _Tp& __t) const noexcept
83+
{
84+
return __t.get_execution_policy();
85+
}
86+
87+
_CCCL_TEMPLATE(class _Env)
88+
_CCCL_REQUIRES(__has_query_get_execution_policy<_Env>)
89+
_CCCL_NODISCARD _CCCL_HIDE_FROM_ABI execution_policy operator()(const _Env& __env) const noexcept
90+
{
91+
static_assert(noexcept(__env.query(*this)));
92+
return __env.query(*this);
93+
}
94+
};
95+
96+
_CCCL_GLOBAL_CONSTANT get_execution_policy_t get_execution_policy{};
97+
6098
} // namespace cuda::experimental::execution
6199

62100
#endif //__CUDAX___EXECUTION_POLICY_CUH

cudax/include/cuda/experimental/__memory_resource/any_resource.cuh

+19
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,16 @@ public:
233233
*this = _CUDA_VSTD::move(__tmp);
234234
}
235235

236+
//! @brief Equality comparison between two \c basic_any_resource
237+
//! @param __rhs The other \c basic_any_resource
238+
//! @return Checks whether both resources have the same equality function stored in their vtable and if so returns
239+
//! the result of that equality comparison. Otherwise returns false.
240+
_CCCL_NODISCARD bool operator==(const basic_any_resource& __rhs) const
241+
{
242+
return (this->__static_vtable->__equal_fn == __rhs.__static_vtable->__equal_fn)
243+
&& this->__static_vtable->__equal_fn(this->_Get_object(), __rhs._Get_object());
244+
}
245+
236246
//! @brief Equality comparison between two \c basic_any_resource
237247
//! @param __rhs The other \c basic_any_resource
238248
//! @return Checks whether both resources have the same equality function stored in their vtable and if so returns
@@ -246,6 +256,15 @@ public:
246256
&& this->__static_vtable->__equal_fn(this->_Get_object(), __rhs._Get_object());
247257
}
248258

259+
//! @brief Inequality comparison between two \c basic_any_resource
260+
//! @param __rhs The other \c basic_any_resource
261+
//! @return Checks whether both resources have the same equality function stored in their vtable and if so returns
262+
//! the inverse result of that equality comparison. Otherwise returns true.
263+
_CCCL_NODISCARD bool operator!=(const basic_any_resource& __rhs) const
264+
{
265+
return !(*this == __rhs);
266+
}
267+
249268
//! @brief Inequality comparison between two \c basic_any_resource
250269
//! @param __rhs The other \c basic_any_resource
251270
//! @return Checks whether both resources have the same equality function stored in their vtable and if so returns
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// Part of CUDA Experimental in CUDA C++ Core Libraries,
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) 2024 NVIDIA CORPORATION & AFFILIATES.
8+
//
9+
//===----------------------------------------------------------------------===//
10+
11+
#ifndef _CUDAX__MEMORY_RESOURCE_GET_MEMORY_RESOURCE_CUH
12+
#define _CUDAX__MEMORY_RESOURCE_GET_MEMORY_RESOURCE_CUH
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 the memory resource header was included without the experimental flag,
25+
// tell the user to define the experimental flag.
26+
#if defined(_CUDA_MEMORY_RESOURCE) && !defined(LIBCUDACXX_ENABLE_EXPERIMENTAL_MEMORY_RESOURCE)
27+
# error "To use the experimental memory resource, define LIBCUDACXX_ENABLE_EXPERIMENTAL_MEMORY_RESOURCE"
28+
#endif
29+
30+
// cuda::mr is unavable on MSVC 2017
31+
#if defined(_CCCL_COMPILER_MSVC_2017)
32+
# error "The any_resource header is not supported on MSVC 2017"
33+
#endif
34+
35+
#if !defined(LIBCUDACXX_ENABLE_EXPERIMENTAL_MEMORY_RESOURCE)
36+
# define LIBCUDACXX_ENABLE_EXPERIMENTAL_MEMORY_RESOURCE
37+
#endif
38+
39+
#include <cuda/__memory_resource/properties.h>
40+
#include <cuda/std/__type_traits/is_same.h>
41+
42+
#include <cuda/experimental/__async/sender/queries.cuh>
43+
#include <cuda/experimental/__memory_resource/any_resource.cuh>
44+
45+
namespace cuda::experimental
46+
{
47+
48+
struct get_memory_resource_t;
49+
50+
template <class _Tp>
51+
_CCCL_CONCEPT __has_member_get_resource = _CCCL_REQUIRES_EXPR((_Tp), const _Tp& __t)(
52+
requires(_CUDA_VMR::async_resource<cuda::std::remove_cvref_t<decltype(__t.get_memory_resource())>>));
53+
54+
template <class _Env>
55+
_CCCL_CONCEPT __has_query_get_memory_resource = _CCCL_REQUIRES_EXPR((_Env))(
56+
requires(!__has_member_get_resource<_Env>),
57+
requires(
58+
_CUDA_VMR::async_resource<cuda::std::remove_cvref_t<__async::__query_result_t<const _Env&, get_memory_resource_t>>>));
59+
60+
//! @brief `get_memory_resource_t` is a customization point object that queries a type `T` for an associated memory
61+
//! resource
62+
struct get_memory_resource_t
63+
{
64+
_CCCL_TEMPLATE(class _Tp)
65+
_CCCL_REQUIRES(__has_member_get_resource<_Tp>)
66+
_CCCL_NODISCARD _CCCL_HIDE_FROM_ABI constexpr decltype(auto) operator()(const _Tp& __t) const noexcept
67+
{
68+
static_assert(noexcept(__t.get_memory_resource()), "get_memory_resource must be noexcept");
69+
return __t.get_memory_resource();
70+
}
71+
72+
_CCCL_TEMPLATE(class _Env)
73+
_CCCL_REQUIRES(__has_query_get_memory_resource<_Env>)
74+
_CCCL_NODISCARD _CCCL_HIDE_FROM_ABI constexpr decltype(auto) operator()(const _Env& __env) const noexcept
75+
{
76+
static_assert(noexcept(__env.query(*this)), "get_memory_resource_t query must be noexcept");
77+
return __env.query(*this);
78+
}
79+
};
80+
81+
_CCCL_GLOBAL_CONSTANT auto get_memory_resource = get_memory_resource_t{};
82+
83+
} // namespace cuda::experimental
84+
85+
#endif //_CUDAX__MEMORY_RESOURCE_GET_MEMORY_RESOURCE_CUH

cudax/include/cuda/experimental/__stream/get_stream.cuh

+19-12
Original file line numberDiff line numberDiff line change
@@ -29,25 +29,33 @@
2929
#include <cuda/std/__type_traits/is_convertible.h>
3030
#include <cuda/stream_ref>
3131

32+
#include <cuda/experimental/__async/sender/queries.cuh>
3233
#include <cuda/experimental/__stream/stream.cuh>
3334

3435
namespace cuda::experimental
3536
{
36-
// clang-format off
37+
38+
struct get_stream_t;
39+
3740
template <class _Tp>
38-
_CCCL_CONCEPT __has_member_get_stream =
39-
_CCCL_REQUIRES_EXPR((_Tp), const _Tp& __t)
40-
(
41-
requires(!_CUDA_VSTD::convertible_to<_Tp, ::cuda::stream_ref>),
42-
_Same_as(::cuda::stream_ref) __t.get_stream()
43-
);
44-
// clang-format on
41+
_CCCL_CONCEPT __convertible_to_stream_ref = _CUDA_VSTD::convertible_to<_Tp, ::cuda::stream_ref>;
42+
43+
template <class _Tp>
44+
_CCCL_CONCEPT __has_member_get_stream = _CCCL_REQUIRES_EXPR((_Tp), const _Tp& __t)(
45+
requires(!__convertible_to_stream_ref<_Tp>), //
46+
requires(__convertible_to_stream_ref<decltype(__t.get_stream())>));
47+
48+
template <class _Env>
49+
_CCCL_CONCEPT __has_query_get_stream = _CCCL_REQUIRES_EXPR((_Env), const _Env& __env, const get_stream_t& __cpo)(
50+
requires(!__convertible_to_stream_ref<_Env>),
51+
requires(!__has_member_get_stream<_Env>),
52+
requires(__convertible_to_stream_ref<decltype(__env.query(__cpo))>));
4553

4654
//! @brief `get_stream` is a customization point object that queries a type `T` for an associated stream
4755
struct get_stream_t
4856
{
4957
_CCCL_TEMPLATE(class _Tp)
50-
_CCCL_REQUIRES((_CUDA_VSTD::convertible_to<_Tp, ::cuda::stream_ref>) )
58+
_CCCL_REQUIRES(__convertible_to_stream_ref<_Tp>)
5159
_CCCL_NODISCARD _CCCL_HIDE_FROM_ABI constexpr ::cuda::stream_ref operator()(const _Tp& __t) const
5260
noexcept(noexcept(static_cast<::cuda::stream_ref>(__t)))
5361
{
@@ -62,9 +70,8 @@ struct get_stream_t
6270
return __t.get_stream();
6371
}
6472

65-
_CCCL_TEMPLATE(class _Env,
66-
class _Ret = decltype(_CUDA_VSTD::declval<const _Env&>().query(_CUDA_VSTD::declval<get_stream_t>())))
67-
_CCCL_REQUIRES(_CCCL_TRAIT(_CUDA_VSTD::is_convertible, _Ret, ::cuda::stream_ref))
73+
_CCCL_TEMPLATE(class _Env)
74+
_CCCL_REQUIRES(__has_query_get_stream<_Env>)
6875
_CCCL_NODISCARD _CCCL_HIDE_FROM_ABI constexpr ::cuda::stream_ref operator()(const _Env& __env) const noexcept
6976
{
7077
static_assert(noexcept(__env.query(*this)), "");

cudax/include/cuda/experimental/execution.cuh

+1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#ifndef __CUDAX_EXECUTION__
1212
#define __CUDAX_EXECUTION__
1313

14+
#include <cuda/experimental/__execution/env.cuh>
1415
#include <cuda/experimental/__execution/policy.cuh>
1516

1617
#endif // __CUDAX_EXECUTION__

cudax/include/cuda/experimental/memory_resource.cuh

+1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include <cuda/experimental/__memory_resource/any_resource.cuh>
1515
#include <cuda/experimental/__memory_resource/device_memory_pool.cuh>
1616
#include <cuda/experimental/__memory_resource/device_memory_resource.cuh>
17+
#include <cuda/experimental/__memory_resource/get_memory_resource.cuh>
1718
#include <cuda/experimental/__memory_resource/managed_memory_resource.cuh>
1819
#include <cuda/experimental/__memory_resource/pinned_memory_resource.cuh>
1920
#include <cuda/experimental/__memory_resource/properties.cuh>

cudax/test/CMakeLists.txt

+3
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,9 @@ foreach(cn_target IN LISTS cudax_TARGETS)
8787
target_compile_options(${test_target} PRIVATE $<$<COMPILE_LANG_AND_ID:CUDA,NVIDIA>:--extended-lambda>)
8888

8989
cudax_add_catch2_test(test_target execution ${cn_target}
90+
execution/env.cu
9091
execution/policies/policies.cu
92+
execution/policies/get_execution_policy.cu
9193
)
9294

9395
cudax_add_catch2_test(test_target stream ${cn_target}
@@ -110,6 +112,7 @@ foreach(cn_target IN LISTS cudax_TARGETS)
110112
memory_resource/any_resource.cu
111113
memory_resource/device_memory_pool.cu
112114
memory_resource/device_memory_resource.cu
115+
memory_resource/get_memory_resource.cu
113116
memory_resource/managed_memory_resource.cu
114117
memory_resource/pinned_memory_resource.cu
115118
memory_resource/shared_resource.cu

0 commit comments

Comments
 (0)