内存资源

namespace mr
group 内存资源

类型别名

using device_resource_ref = cuda::mr::resource_ref<cuda::mr::device_accessible>

cuda::mr::resource_ref 的别名,具有属性 cuda::mr::device_accessible

using device_async_resource_ref = cuda::mr::async_resource_ref<cuda::mr::device_accessible>

cuda::mr::async_resource_ref 的别名,具有属性 cuda::mr::device_accessible

using host_resource_ref = cuda::mr::resource_ref<cuda::mr::host_accessible>

cuda::mr::resource_ref 的别名,具有属性 cuda::mr::host_accessible

using host_async_resource_ref = cuda::mr::async_resource_ref<cuda::mr::host_accessible>

cuda::mr::async_resource_ref 的别名,具有属性 cuda::mr::host_accessible

using host_device_resource_ref = cuda::mr::resource_ref<cuda::mr::host_accessible, cuda::mr::device_accessible>

cuda::mr::resource_ref 的别名,具有属性 cuda::mr::host_accessiblecuda::mr::device_accessible

using host_device_async_resource_ref = cuda::mr::async_resource_ref<cuda::mr::host_accessible, cuda::mr::device_accessible>

cuda::mr::async_resource_ref 的别名,具有属性 cuda::mr::host_accessiblecuda::mr::device_accessible

函数

inline device_memory_resource *get_per_device_resource(cuda_device_id device_id)

获取指定设备的资源。

返回指定设备的 device_memory_resource 的指针。初始资源是 cuda_memory_resource

device_id.value() 必须在范围 [0, cudaGetDeviceCount()) 内,否则行为未定义。

此函数在并行调用 set_per_device_resourceget_per_device_resourceget_current_device_resourceset_current_device_resource 时是线程安全的。对这些函数中任何一个的并行调用将导致有效状态,但执行顺序未定义。

注意

返回的 device_memory_resource 仅应在 CUDA 设备 device_id 是当前设备时使用(例如使用 cudaSetDevice() 设置)。如果在活动 CUDA 设备与创建 device_memory_resource 时活动设备不同时使用 device_memory_resource,则其行为未定义。

参数:

device_id – 目标设备的 id

返回:

设备 device_id 的当前 device_memory_resource 指针

inline device_memory_resource *set_per_device_resource(cuda_device_id device_id, device_memory_resource *new_mr)

设置指定设备的 device_memory_resource

如果 new_mr 不是 nullptr,则将由 id 指定的设备的内存资源指针设置为 new_mr。否则,将 id 的资源重置为初始的 cuda_memory_resource

id.value() 必须在范围 [0, cudaGetDeviceCount()) 内,否则行为未定义。

new_mr 指向的对象必须在资源最后一次使用之后仍然存在,否则行为未定义。调用方负责维护资源对象的生命周期。

此函数在并行调用 set_per_device_resourceget_per_device_resourceget_current_device_resourceset_current_device_resource 时是线程安全的。对这些函数中任何一个的并行调用将导致有效状态,但执行顺序未定义。

注意

传入 new_mr 的资源必须在设备 id 是当前 CUDA 设备时创建(例如使用 cudaSetDevice() 设置)。如果在活动 CUDA 设备与创建 device_memory_resource 时活动设备不同时使用 device_memory_resource,则其行为未定义。

参数:
  • device_id – 目标设备的 id

  • new_mr – 如果不是 nullptr,则为新的 device_memory_resource 指针,用作 id 的新资源

返回:

id 的先前内存资源指针

inline device_memory_resource *get_current_device_resource()

获取当前设备的内存资源。

返回为当前设备设置的资源的指针。初始资源是 cuda_memory_resource

“当前设备”是 cudaGetDevice 返回的设备。

此函数在并行调用 set_per_device_resourceget_per_device_resourceget_current_device_resourceset_current_device_resource 时是线程安全的。对这些函数中任何一个的并行调用将导致有效状态,但执行顺序未定义。

注意

返回的 device_memory_resource 仅应与当前 CUDA 设备一起使用。更改当前设备(例如使用 cudaSetDevice())然后使用返回的资源可能导致未定义的行为。如果在活动 CUDA 设备与创建 device_memory_resource 时活动设备不同时使用 device_memory_resource,则其行为未定义。

返回:

当前设备的资源指针

inline device_memory_resource *set_current_device_resource(device_memory_resource *new_mr)

设置当前设备的内存资源。

如果 new_mr 不是 nullptr,则将当前设备的资源指针设置为 new_mr。否则,将资源重置为初始的 cuda_memory_resource

“当前设备”是 cudaGetDevice 返回的设备。

new_mr 指向的对象必须在资源最后一次使用之后仍然存在,否则行为未定义。调用方负责维护资源对象的生命周期。

此函数在并行调用 set_per_device_resourceget_per_device_resourceget_current_device_resourceset_current_device_resource 时是线程安全的。对这些函数中任何一个的并行调用将导致有效状态,但执行顺序未定义。

注意

传入 new_mr 的资源必须为当前 CUDA 设备创建。如果在活动 CUDA 设备与创建 device_memory_resource 时活动设备不同时使用 device_memory_resource,则其行为未定义。

参数:

new_mr – 如果不是 nullptr,则为新的资源指针,用作当前设备的资源

返回:

当前设备的先前资源指针

inline device_async_resource_ref get_per_device_resource_ref(cuda_device_id device_id)

获取指定设备的 device_async_resource_ref

返回指定设备的 device_async_resource_ref。初始的 resource_ref 引用一个 cuda_memory_resource

device_id.value() 必须在范围 [0, cudaGetDeviceCount()) 内,否则行为未定义。

此函数在并行调用 set_per_device_resource_refget_per_device_resource_refget_current_device_resource_refset_current_device_resource_ref 和 `reset_current_device_resource_ref 时是线程安全的。对这些函数中任何一个的并行调用将导致有效状态,但执行顺序未定义。

注意

返回的 device_async_resource_ref 仅应在 CUDA 设备 device_id 是当前设备时使用(例如使用 cudaSetDevice() 设置)。如果在活动 CUDA 设备与创建内存资源时活动设备不同时使用 device_async_resource_ref,则其行为未定义。

参数:

device_id – 目标设备的 id

返回:

设备 device_id 的当前 device_async_resource_ref

inline device_async_resource_ref set_per_device_resource_ref(cuda_device_id device_id, device_async_resource_ref new_resource_ref)

将指定设备的 device_async_resource_ref 设置为 new_resource_ref

device_id.value() 必须在范围 [0, cudaGetDeviceCount()) 内,否则行为未定义。

new_resource_ref 引用的对象必须在资源最后一次使用之后仍然存在,否则行为未定义。调用方负责维护资源对象的生命周期。

此函数在并行调用 set_per_device_resource_refget_per_device_resource_refget_current_device_resource_refset_current_device_resource_ref 和 `reset_current_device_resource_ref 时是线程安全的。对这些函数中任何一个的并行调用将导致有效状态,但执行顺序未定义。

注意

传入 new_resource_ref 的资源必须在设备 device_id 是当前 CUDA 设备时创建(例如使用 cudaSetDevice() 设置)。如果在活动 CUDA 设备与创建内存资源时活动设备不同时使用 device_async_resource_ref,则其行为未定义。

参数:
  • device_id – 目标设备的 id

  • new_resource_ref – 用于 device_id 的新的 device_async_resource_ref

返回:

设备 device_id 的先前的 device_async_resource_ref

inline device_async_resource_ref get_current_device_resource_ref()

获取当前设备的 device_async_resource_ref

返回为当前设备设置的 device_async_resource_ref。初始的 resource_ref 引用一个 cuda_memory_resource

“当前设备”是 cudaGetDevice 返回的设备。

此函数在并行调用 set_per_device_resource_refget_per_device_resource_refget_current_device_resource_refset_current_device_resource_ref 和 `reset_current_device_resource_ref 时是线程安全的。对这些函数中任何一个的并行调用将导致有效状态,但执行顺序未定义。

注意

返回的 device_async_resource_ref 仅应与当前 CUDA 设备一起使用。更改当前设备(例如使用 cudaSetDevice())然后使用返回的 resource_ref 可能导致未定义的行为。如果在活动 CUDA 设备与创建内存资源时活动设备不同时使用 device_async_resource_ref,则其行为未定义。

返回:

当前设备的活动 device_async_resource_ref

inline device_async_resource_ref set_current_device_resource_ref(device_async_resource_ref new_resource_ref)

设置当前设备的 device_async_resource_ref

“当前设备”是 cudaGetDevice 返回的设备。

new_resource_ref 引用的对象必须在资源最后一次使用之后仍然存在,否则行为未定义。调用方负责维护资源对象的生命周期。

此函数在并行调用 set_per_device_resource_refget_per_device_resource_refget_current_device_resource_refset_current_device_resource_ref 和 `reset_current_device_resource_ref 时是线程安全的。对这些函数中任何一个的并行调用将导致有效状态,但执行顺序未定义。

注意

传入 new_resource 的资源必须为当前 CUDA 设备创建。如果在活动 CUDA 设备与创建内存资源时活动设备不同时使用 device_async_resource_ref,则其行为未定义。

参数:

new_resource_ref – 用于当前设备的新的 device_async_resource_ref

返回:

当前设备的先前的 device_async_resource_ref

inline device_async_resource_ref reset_per_device_resource_ref(cuda_device_id device_id)

将指定设备的 device_async_resource_ref 重置为初始资源。

重置为对初始 cuda_memory_resource 的引用。

device_id.value() 必须在范围 [0, cudaGetDeviceCount()) 内,否则行为未定义。

此函数在并行调用 set_per_device_resource_refget_per_device_resource_refget_current_device_resource_refset_current_device_resource_ref 和 `reset_current_device_resource_ref 时是线程安全的。对这些函数中任何一个的并行调用将导致有效状态,但执行顺序未定义。

参数:

device_id – 目标设备的 id

返回:

设备 device_id 的先前的 device_async_resource_ref

inline device_async_resource_ref reset_current_device_resource_ref()

将当前设备的 device_async_resource_ref 重置为初始资源。

重置为对初始 cuda_memory_resource 的引用。“当前设备”是 cudaGetDevice 返回的设备。

此函数在并行调用 set_per_device_resource_refget_per_device_resource_refget_current_device_resource_refset_current_device_resource_ref 和 `reset_current_device_resource_ref 时是线程安全的。对这些函数中任何一个的并行调用将导致有效状态,但执行顺序未定义。

返回:

设备 device_id 的先前的 device_async_resource_ref

template<class Resource>
device_async_resource_ref to_device_async_resource_ref_checked(Resource *res)

将内存资源指针转换为 device_async_resource_ref,并检查是否为 nullptr

模板参数:

Resource – 内存资源的类型。

参数:

res – 内存资源的指针。

抛出:

std::logic_error – 如果内存资源指针为空。

返回:

一个指向内存资源的 device_async_resource_ref

变量

template<class Resource, class = void>
constexpr bool is_resource_adaptor = false

通过检查是否存在 get_upstream_resource 来检查资源是否为资源适配器的概念。

class pinned_host_memory_resource
#include <pinned_host_memory_resource.hpp>

用于分配固定主机内存的内存资源类。

此类使用 CUDA 的 cudaHostAlloc 分配固定主机内存。它实现了 cuda::mr::memory_resourcecuda::mr::device_memory_resource 概念,以及 cuda::mr::host_accessiblecuda::mr::device_accessible 属性。

公共函数

inline bool operator==(const pinned_host_memory_resource&) const

如果指定的资源与此资源类型相同,则为 true。

返回:

如果指定的资源与此资源类型相同,则为 true。

inline bool operator!=(const pinned_host_memory_resource&) const

如果指定的资源与此资源类型不同,则为 true,否则为 false。

返回:

如果指定的资源与此资源类型不同,则为 true,否则为 false。

公共静态函数

static inline void *allocate(std::size_t bytes, [[maybe_unused]] std::size_t alignment = rmm::RMM_DEFAULT_HOST_ALIGNMENT)

分配至少 bytes 字节的固定主机内存。

抛出:
  • rmm::out_of_memory – 如果由于 CUDA 内存不足错误而无法满足请求的分配。

  • rmm::bad_alloc – 如果由于任何其他原因而无法满足请求的分配。

参数:
  • bytes – 分配的大小,以字节为单位。

  • alignment – 对齐方式,以字节为单位。如果未指定,则使用默认对齐方式。

返回:

指向新分配内存的指针。

static inline void *deallocate(void *ptr, std::size_t bytes, std::size_t alignment = rmm::RMM_DEFAULT_HOST_ALIGNMENT) noexcept

释放由 ptr 指向的大小为 bytes 字节的内存。

参数:
  • ptr – 要释放的指针。

  • bytes – 分配的大小。

  • alignment – 对齐方式,以字节为单位。如果未指定,则使用默认对齐方式。

static inline void *allocate_async(std::size_t bytes, [[maybe_unused]] cuda::stream_ref stream)

分配至少 bytes 字节的固定主机内存。

注意

流参数被忽略,行为与 allocate 相同。

抛出:
  • rmm::out_of_memory – 如果由于 CUDA 内存不足错误而无法满足请求的分配。

  • rmm::bad_alloc – 如果由于任何其他错误而无法满足请求的分配。

参数:
  • bytes – 分配的大小,以字节为单位。

  • stream – 在其上执行分配的 CUDA 流(被忽略)。

返回:

指向新分配内存的指针。

static inline void *allocate_async(std::size_t bytes, std::size_t alignment, [[maybe_unused]] cuda::stream_ref stream)

分配至少 bytes 字节且对齐方式为 alignment 的固定主机内存。

注意

流参数被忽略,行为与 allocate 相同。

抛出:
  • rmm::out_of_memory – 如果由于 CUDA 内存不足错误而无法满足请求的分配。

  • rmm::bad_alloc – 如果由于任何其他错误而无法满足请求的分配。

参数:
  • bytes – 分配的大小,以字节为单位。

  • alignment – 对齐方式,以字节为单位。

  • stream – 在其上执行分配的 CUDA 流(被忽略)。

返回:

指向新分配内存的指针。

static inline void *deallocate_async(void *ptr, std::size_t bytes, [[maybe_unused]] cuda::stream_ref stream) noexcept

释放由 ptr 指向的大小为 bytes 字节的内存。

注意

流参数被忽略,行为与 deallocate 相同。

参数:
  • ptr – 要释放的指针。

  • bytes – 分配的大小。

  • stream – 在其上执行释放的 CUDA 流(被忽略)。

static inline void *deallocate_async(void *ptr, std::size_t bytes, std::size_t alignment, [[maybe_unused]] cuda::stream_ref stream) noexcept

释放由 ptr 指向的大小为 bytes 字节且对齐方式为 alignment 字节的内存。

注意

流参数被忽略,行为与 deallocate 相同。

参数:
  • ptr – 要释放的指针。

  • bytes – 分配的大小。

  • alignment – 对齐方式,以字节为单位。

  • stream – 在其上执行释放的 CUDA 流(被忽略)。

友元

inline friend void get_property(pinned_host_memory_resource const&, cuda::mr::device_accessible) noexcept

启用 cuda::mr::device_accessible 属性。

此属性声明 pinned_host_memory_resource 提供设备可访问内存

inline friend void get_property(pinned_host_memory_resource const&, cuda::mr::host_accessible) noexcept

启用 cuda::mr::host_accessible 属性。

此属性声明 pinned_host_memory_resource 提供主机可访问内存

group 设备内存资源

类型别名

using allocate_callback_t = std::function<void*(std::size_t, cuda_stream_view, void*)>

回调内存资源用于分配的回调函数类型。

回调函数的签名是:`void* allocate_callback_t(std::size_t bytes, cuda_stream_view stream, void* arg);`

  • 返回一个指针,指向在 stream 上可立即使用的至少 bytes 字节的分配。流有序行为要求与 device_memory_resource::allocate 相同。

  • 此签名与 do_allocate 兼容,但添加了额外的函数参数 argarg 提供给 callback_memory_resource 的构造函数,并将被转发到每次回调函数调用。

using deallocate_callback_t = std::function<void(void*, std::size_t, cuda_stream_view, void*)>

callback_memory_resource 用于释放的回调函数类型。

回调函数的签名是:`void deallocate_callback_t(void* ptr, std::size_t bytes, cuda_stream_view stream, void* arg);`

  • 释放由 ptr 指向的内存。bytes 指定分配的大小(以字节为单位),并且必须等于传递给分配回调函数时的 bytes 值。流有序行为要求与 device_memory_resource::deallocate 相同。

  • 此签名与 do_deallocate 兼容,但添加了额外的函数参数 argarg 提供给 callback_memory_resource 的构造函数,并将被转发到每次回调函数调用。

函数

template<typename T, typename U>
bool operator==(polymorphic_allocator<T> const &lhs, polymorphic_allocator<U> const &rhs)

比较两个 polymorphic_allocator 是否相等。

如果两个 polymorphic_allocator 的底层内存资源比较相等,则它们相等。

模板参数:
  • T – 第一个分配器的类型

  • U – 第二个分配器的类型

参数:
  • lhs – 要比较的第一个分配器

  • rhs – 要比较的第二个分配器

返回:

如果两个分配器相等,则为 true,否则为 false

template<typename T, typename U>
bool operator!=(polymorphic_allocator<T> const &lhs, polymorphic_allocator<U> const &rhs)

比较两个 polymorphic_allocator 是否不相等。

如果两个 polymorphic_allocator 的底层内存资源比较不相等,则它们不相等。

模板参数:
  • T – 第一个分配器的类型

  • U – 第二个分配器的类型

参数:
  • lhs – 要比较的第一个分配器

  • rhs – 要比较的第二个分配器

返回:

如果两个分配器不相等,则为 true,否则为 false

template<typename A, typename O>
bool operator==(stream_allocator_adaptor<A> const &lhs, stream_allocator_adaptor<O> const &rhs)

比较两个 stream_allocator_adaptor 是否相等。

如果两个 stream_allocator_adaptor 的底层分配器比较相等,则它们相等。

模板参数:
  • A – 第一个分配器的类型

  • O – 第二个分配器的类型

参数:
  • lhs – 要比较的第一个分配器

  • rhs – 要比较的第二个分配器

返回:

如果两个分配器相等,则为 true,否则为 false

template<typename A, typename O>
bool operator!=(stream_allocator_adaptor<A> const &lhs, stream_allocator_adaptor<O> const &rhs)

比较两个 stream_allocator_adaptor 是否不相等。

如果两个 stream_allocator_adaptor 的底层分配器比较不相等,则它们不相等。

模板参数:
  • A – 第一个分配器的类型

  • O – 第二个分配器的类型

参数:
  • lhs – 要比较的第一个分配器

  • rhs – 要比较的第二个分配器

返回:

如果两个分配器不相等,则为 true,否则为 false

template<typename Upstream>
class arena_memory_resource : public rmm::mr::device_memory_resource
#include <arena_memory_resource.hpp>

一种子分配器,强调避免碎片和可伸缩的并发支持。

分配 (do_allocate()) 和释放 (do_deallocate()) 是线程安全的。此外,此类与 CUDA 每线程默认流兼容。

GPU 内存被划分为一个全局 arena、用于默认流的每线程 arena 以及用于非默认流的每流 arena。每个 arena 从全局 arena 中以称为 superblocks 的块分配内存。

每个 arena 中的块使用地址排序的首次适应法进行分配。当块被释放时,如果地址是连续的,则与相邻的空闲块合并。空闲的 superblocks 返回到全局 arena。

在实际应用中,分配大小倾向于遵循幂律分布,其中大型分配很少见,但小型分配相当常见。通过在每线程 arena 中处理小型分配,可以在高并发下获得足够的性能而不会引入过多的内存碎片。

此设计受到几个针对多线程应用的现有 CPU 内存分配器(glibc malloc、Hoard、jemalloc、TCMalloc)的启发,尽管形式更简单。未来可能的改进包括使用大小类、分配缓存以及更细粒度的锁定或无锁方法。

另请参阅

Wilson, P. R., Johnstone, M. S., Neely, M., & Boles, D. (1995, September). Dynamic storage allocation: A survey and critical review. In International Workshop on Memory Management (pp. 1-116). Springer, Berlin, Heidelberg.

另请参阅

Berger, E. D., McKinley, K. S., Blumofe, R. D., & Wilson, P. R. (2000). Hoard: A scalable memory allocator for multithreaded applications. ACM Sigplan Notices, 35(11), 117-128.

另请参阅

Evans, J. (2006, April). A scalable concurrent malloc (3) implementation for FreeBSD. In Proc. of the bsdcan conference, ottawa, canada.

另请参阅

http://hoard.org/

另请参阅

http://jemalloc.net/

模板参数:

上游资源 – 用于为全局 arena 分配内存的内存资源。实现 rmm::mr::device_memory_resource 接口。

公共函数

inline explicit arena_memory_resource(device_async_resource_ref upstream_mr, std::optional<std::size_t> arena_size = std::nullopt, bool dump_log_on_failure = false)

构造一个 arena_memory_resource

参数:
  • upstream_mr – 用于为全局 arena 分配块的内存资源。

  • arena_size – 全局 arena 的大小,以字节为单位。默认为当前设备可用内存的一半。

  • dump_log_on_failure – 如果为 true,则在内存不足时转储内存日志。

inline explicit arena_memory_resource(Upstream *upstream_mr, std::optional<std::size_t> arena_size = std::nullopt, bool dump_log_on_failure = false)

构造一个 arena_memory_resource

抛出:

rmm::logic_error – 如果 upstream_mr == nullptr

参数:
  • upstream_mr – 用于为全局 arena 分配块的内存资源。

  • arena_size – 全局 arena 的大小,以字节为单位。默认为当前设备可用内存的一半。

  • dump_log_on_failure – 如果为 true,则在内存不足时转储内存日志。

template<typename Upstream>
class binning_memory_resource : public rmm::mr::device_memory_resource
#include <binning_memory_resource.hpp>

从与 bin 大小相关的上游资源分配内存。

模板参数:

UpstreamResource – 用于分配不属于任何配置 bin 大小的内存的 memory_resource。实现 rmm::mr::device_memory_resource 接口。

公共函数

inline explicit binning_memory_resource(device_async_resource_ref upstream_resource)

构造一个新的 binning memory resource 对象。

最初没有 bins,因此只需使用 upstream_resource,直到使用 add_bin 添加 bin 资源。

参数:

upstream_resource – 用于分配 bin 池的上游内存资源。

inline explicit binning_memory_resource(Upstream *upstream_resource)

构造一个新的 binning memory resource 对象。

最初没有 bins,因此只需使用 upstream_resource,直到使用 add_bin 添加 bin 资源。

抛出:

rmm::logic_error – 如果 upstream_resource 为 nullptr

参数:

upstream_resource – 用于分配 bin 池的上游内存资源。

inline binning_memory_resource(device_async_resource_ref upstream_resource, int8_t min_size_exponent, int8_t max_size_exponent)

构造一个带有一系列初始 bin 的 binning memory resource 对象。

构造一个新的 binning memory resource 并添加由范围 [2^min_size_exponent, 2^max_size_exponent] 内的 fixed_size_memory_resource 支持的 bin。例如,如果 min_size_exponent==18max_size_exponent==22,则创建大小为 256KiB, 512KiB, 1024KiB, 2048KiB 和 4096KiB 的 bin。

参数:
  • upstream_resource – 用于分配 bin 池的上游内存资源。

  • min_size_exponent – 最小的基数为 2 的指数 bin 大小。

  • max_size_exponent – 最大的基数为 2 的指数 bin 大小。

inline binning_memory_resource(Upstream *upstream_resource, int8_t min_size_exponent, int8_t max_size_exponent)

构造一个带有一系列初始 bin 的 binning memory resource 对象。

构造一个新的 binning memory resource 并添加由范围 [2^min_size_exponent, 2^max_size_exponent] 内的 fixed_size_memory_resource 支持的 bin。例如,如果 min_size_exponent==18max_size_exponent==22,则创建大小为 256KiB, 512KiB, 1024KiB, 2048KiB 和 4096KiB 的 bin。

抛出:

rmm::logic_error – 如果 upstream_resource 为 nullptr

参数:
  • upstream_resource – 用于分配 bin 池的上游内存资源。

  • min_size_exponent – 最小的基数为 2 的指数 bin 大小。

  • max_size_exponent – 最大的基数为 2 的指数 bin 大小。

~binning_memory_resource() override = default

销毁 binning_memory_resource 并释放从上游资源分配的所有内存。

inline device_async_resource_ref get_upstream_resource() const noexcept

指向的上游资源的 device_async_resource_ref

返回:

指向的上游资源的 device_async_resource_ref

inline void add_bin(std::size_t allocation_size, std::optional<device_async_resource_ref> bin_resource = std::nullopt)

向此资源添加一个 bin 分配器。

如果提供了 bin_resource,则添加它;否则构造并添加一个 fixed_size_memory_resource

这个 bin 将用于任何小于 allocation_size 且大于下一个较小 bin 分配大小的分配。

如果已经存在指定大小的 bin,则不进行任何更改。

此函数不是线程安全的。

参数:
  • allocation_size – 此 bin 分配的最大大小

  • bin_resource – bin 的内存资源

class callback_memory_resource : public rmm::mr::device_memory_resource
#include <callback_memory_resource.hpp>

使用提供的回调函数进行内存分配和释放的设备内存资源。

公共函数

inline callback_memory_resource(allocate_callback_t allocate_callback, deallocate_callback_t deallocate_callback, void *allocate_callback_arg = nullptr, void *deallocate_callback_arg = nullptr) noexcept

构造一个新的 callback memory resource。

构造一个 callback memory resource,它使用用户提供的回调函数 allocate_callback 进行分配,使用 deallocate_callback 进行释放。

参数:
  • allocate_callback – 用于分配的回调函数

  • deallocate_callback – 用于释放的回调函数

  • allocate_callback_arg – 传递给 allocate_callback 的附加上下文。调用者有责任在 callback_memory_resource 的生命周期内维护指向的数据的生命周期。

  • deallocate_callback_arg – 传递给 deallocate_callback 的附加上下文。调用者有责任在 callback_memory_resource 的生命周期内维护指向的数据的生命周期。

callback_memory_resource(callback_memory_resource&&) noexcept = default

默认移动构造函数。

callback_memory_resource &operator=(callback_memory_resource&&) noexcept = default

默认移动赋值运算符。

返回:

callback_memory_resource& 对赋值对象的引用

class cuda_async_memory_resource : public rmm::mr::device_memory_resource
#include <cuda_async_memory_resource.hpp>

使用 cudaMallocAsync/cudaFreeAsync 进行分配/释放的 device_memory_resource 派生类。

公共类型

enum class allocation_handle_type

用于指定内存分配句柄类型的标志。

注意

这些值完全复制自 cudaMemAllocationHandleType。我们需要在此定义自己的枚举,因为支持异步内存池的最早 CUDA 运行时版本 (CUDA 11.2) 不支持这些标志,所以我们需要一个占位符,以便在 CUDA >= 11.2 的所有版本中都能在 cuda_async_memory_resource 的构造函数中一致地使用。请参阅 https://docs.nvda.net.cn/cuda/cuda-runtime-api/group__CUDART__TYPES.html 上的 cudaMemAllocationHandleType 文档,并确保枚举值与 CUDA 文档保持同步。

enumerator none

不允许任何导出机制。

enumerator posix_file_descriptor

允许使用文件描述符进行导出。仅在 POSIX 系统上允许。

enumerator win32

允许使用 Win32 NT 句柄进行导出。(HANDLE)

enumerator win32_kmt

允许使用 Win32 KMT 句柄进行导出。(D3DKMT_HANDLE)

enumerator fabric

允许使用 fabric 句柄进行导出。(cudaMemFabricHandle_t)

公共函数

inline cuda_async_memory_resource(std::optional<std::size_t> initial_pool_size = {}, std::optional<std::size_t> release_threshold = {}, std::optional<allocation_handle_type> export_handle_type = {})

构造一个 cuda_async_memory_resource,带有所选的初始池大小和释放阈值。

如果池大小超出释放阈值,则池持有的未使用内存将在下一个同步事件时释放。

抛出:

rmm::logic_error – 如果 CUDA 版本不支持 cudaMallocAsync

参数:
  • initial_pool_size – 可选的池初始大小,以字节为单位。如果未提供值,初始池大小为可用 GPU 内存的一半。

  • release_threshold – 可选的池释放阈值大小,以字节为单位。如果未提供值,释放阈值将设置为当前设备上的总内存量。

  • export_handle_type – 可选的 cudaMemAllocationHandleType,表示从此资源进行的分配应支持进程间通信 (IPC)。默认为 cudaMemHandleTypeNone,不支持 IPC。

inline cudaMemPool_t pool_handle() const noexcept

返回底层本地 CUDA 池的句柄。

返回:

cudaMemPool_t 底层 CUDA 池的句柄

class cuda_async_view_memory_resource : public rmm::mr::device_memory_resource
#include <cuda_async_view_memory_resource.hpp>

使用 cudaMallocAsync/cudaFreeAsync 进行分配/释放的 device_memory_resource 派生类。

公共函数

inline cuda_async_view_memory_resource(cudaMemPool_t pool_handle)

构造一个 cuda_async_view_memory_resource,它使用现有的 CUDA 内存池。提供的池不由 cuda_async_view_memory_resource 拥有,并且必须在内存资源的生命周期内保持有效。

抛出:

rmm::logic_error – 如果 CUDA 版本不支持 cudaMallocAsync

参数:

pool_handle – 用于服务分配请求的 CUDA 内存池句柄。

inline cudaMemPool_t pool_handle() const noexcept

返回底层本地 CUDA 池的句柄。

返回:

cudaMemPool_t 底层 CUDA 池的句柄

cuda_async_view_memory_resource(cuda_async_view_memory_resource const&) = default

默认拷贝构造函数。

cuda_async_view_memory_resource(cuda_async_view_memory_resource&&) = default

默认移动构造函数。

cuda_async_view_memory_resource &operator=(cuda_async_view_memory_resource const&) = default

默认拷贝赋值运算符。

返回:

cuda_async_view_memory_resource& 对赋值对象的引用

cuda_async_view_memory_resource &operator=(cuda_async_view_memory_resource&&) = default

默认移动赋值运算符。

返回:

cuda_async_view_memory_resource& 对赋值对象的引用

class cuda_memory_resource : public rmm::mr::device_memory_resource
#include <cuda_memory_resource.hpp>

使用 cudaMalloc/Free 进行分配/释放的 device_memory_resource 派生类。

公共函数

cuda_memory_resource(cuda_memory_resource const&) = default

默认拷贝构造函数。

cuda_memory_resource(cuda_memory_resource&&) = default

默认移动构造函数。

cuda_memory_resource &operator=(cuda_memory_resource const&) = default

默认拷贝赋值运算符。

返回:

cuda_memory_resource& 对赋值对象的引用

cuda_memory_resource &operator=(cuda_memory_resource&&) = default

默认移动赋值运算符。

返回:

cuda_memory_resource& 对赋值对象的引用

class device_memory_resource
#include <device_memory_resource.hpp>

所有 librmm 设备内存分配的基类。

这个类是所有自定义设备内存实现必须满足的接口。

所有派生类必须实现两个私有的纯虚函数:do_allocatedo_deallocate。可选地,派生类还可以重写 is_equal。默认情况下,is_equal 仅执行身份比较。

公共的非虚函数 allocatedeallocateis_equal 只是简单地调用私有虚函数。这样做的原因是允许在基类中实现共享的默认行为。例如,基类的 allocate 函数可能会记录每一次分配,无论使用哪种派生类实现。

allocatedeallocate API 和实现提供了流有序的内存分配。这允许优化,例如在同一流上重新使用已释放的内存,而无需流同步的开销。

调用 allocate(bytes, stream_a)(在任何派生类上)返回一个指针,该指针在 stream_a 上使用是有效的。在不同的流(例如 stream_b)上使用内存是未定义行为,除非这两个流首先同步,例如使用 cudaStreamSynchronize(stream_a) 或在 stream_a 上记录一个 CUDA 事件,然后在 stream_b 上调用 cudaStreamWaitEvent(stream_b, event)

传递给 deallocate() 的流应该是可以在其上立即使用已释放内存进行另一次分配的流。通常这是在调用 deallocate() 之前最后使用该分配的流。传入的流可以由 device_memory_resource 在内部用于以最少的同步管理可用内存,并且也可以在稍后时间同步,例如使用调用 cudaStreamSynchronize()

因此,销毁传递给 deallocate() 的 CUDA 流是未定义行为。如果在调用 deallocate() 之前最后使用该分配的流已被销毁,或者已知该流将被销毁,那么最好同步该流(在销毁之前),然后将不同的流传递给 deallocate()(例如,默认流)。

仅当活动 CUDA 设备与创建 device_memory_resource 时活动的设备相同时,才应使用 device_memory_resource。否则行为未定义。

为每个设备创建 device_memory_resource 需要小心地在创建每个资源之前设置当前设备,并在资源被设置为每个设备资源时维持其生命周期。下面是一个示例循环,它为每个设备创建指向 pool_memory_resource 对象的 unique_ptr,并将它们设置为该设备的每个设备资源。

using pool_mr = rmm::mr::pool_memory_resource<rmm::mr::cuda_memory_resource>;
std::vector<unique_ptr<pool_mr>> per_device_pools;
for(int i = 0; i < N; ++i) {
  cudaSetDevice(i);
  // Note: for brevity, omitting creation of upstream and computing initial_size
  per_device_pools.push_back(std::make_unique<pool_mr>(upstream, initial_size));
  set_per_device_resource(cuda_device_id{i}, &per_device_pools.back());
}

派生自 rmm::mr::aligned_resource_adaptor< Upstream >, rmm::mr::arena_memory_resource< Upstream >, rmm::mr::binning_memory_resource< Upstream >, rmm::mr::callback_memory_resource, rmm::mr::cuda_async_memory_resource, rmm::mr::cuda_async_view_memory_resource, rmm::mr::cuda_memory_resource, rmm::mr::failure_callback_resource_adaptor< Upstream, ExceptionType >, rmm::mr::limiting_resource_adaptor< Upstream >, rmm::mr::logging_resource_adaptor< Upstream >, rmm::mr::managed_memory_resource, rmm::mr::owning_wrapper< Resource, Upstreams >, rmm::mr::prefetch_resource_adaptor< Upstream >, rmm::mr::sam_headroom_memory_resource, rmm::mr::statistics_resource_adaptor< Upstream >, rmm::mr::system_memory_resource, rmm::mr::thread_safe_resource_adaptor< Upstream >, rmm::mr::tracking_resource_adaptor< Upstream >

公共函数

device_memory_resource(device_memory_resource const&) = default

默认拷贝构造函数。

device_memory_resource(device_memory_resource&&) noexcept = default

默认移动构造函数。

device_memory_resource &operator=(device_memory_resource const&) = default

默认拷贝赋值运算符。

返回:

device_memory_resource& 对赋值对象的引用

device_memory_resource &operator=(device_memory_resource&&) noexcept = default

默认移动赋值运算符。

返回:

device_memory_resource& 对赋值对象的引用

inline void *allocate(std::size_t bytes, cuda_stream_view stream = cuda_stream_view{})

分配至少 bytes 大小的内存。

返回的指针将至少具有 256 字节对齐。

如果支持,此操作可以选择在流上执行。否则,流将被忽略,使用空流。

抛出:

rmm::bad_alloc – 当无法在指定 stream 上分配请求的 bytes 时。

参数:
  • bytes – 分配的大小

  • stream – 执行分配的流

返回:

void* 指向新分配内存的指针

inline void deallocate(void *ptr, std::size_t bytes, cuda_stream_view stream = cuda_stream_view{})

释放 p 指向的内存。

p 必须是由先前在与 *this 比较相等的 device_memory_resource 上调用 allocate(bytes, stream) 返回的,并且其指向的存储空间尚未被释放,否则行为未定义。

如果支持,此操作可以选择在流上执行。否则,流将被忽略,使用空流。

参数:
  • ptr – 要释放的指针

  • bytes – 分配的大小,以字节为单位。这必须等于返回 pallocate 调用中传递的 bytes 值。

  • stream – 执行释放的流

inline bool is_equal(device_memory_resource const &other) const noexcept

将此资源与另一个资源进行比较。

两个 device_memory_resource 仅当一个 device_memory_resource 分配的内存可以从另一个释放,反之亦然时才相等。

默认情况下,仅检查 *thisother 是否指向同一对象,即不检查它们是否是同一类的两个对象。

参数:

other – 要比较的另一个资源

返回:

如果两个资源等效

inline void *allocate(std::size_t bytes, std::size_t alignment)

分配至少 bytes 大小的内存。

返回的指针将至少具有 256 字节对齐。

抛出:

rmm::bad_alloc – 当无法在指定 stream 上分配请求的 bytes 时。

参数:
  • bytes – 分配的大小

  • alignment – 分配所需的对齐方式

返回:

void* 指向新分配内存的指针

inline void *deallocate(void *ptr, std::size_t bytes, std::size_t alignment)

释放 p 指向的内存。

p 必须是由先前在与 *this 比较相等的 device_memory_resource 上调用 allocate(bytes, stream) 返回的,并且其指向的存储空间尚未被释放,否则行为未定义。

参数:
  • ptr – 要释放的指针

  • bytes – 分配的大小,以字节为单位。这必须等于返回 pallocate 调用中传递的 bytes 值。

  • alignment – 返回 pallocate 调用中传递的对齐方式

inline void *allocate_async(std::size_t bytes, std::size_t alignment, cuda_stream_view stream)

分配至少 bytes 大小的内存。

返回的指针将至少具有 256 字节对齐。

抛出:

rmm::bad_alloc – 当无法在指定 stream 上分配请求的 bytes 时。

参数:
  • bytes – 分配的大小

  • alignment – 分配所需的对齐方式

  • stream – 执行分配的流

返回:

void* 指向新分配内存的指针

inline void *allocate_async(std::size_t bytes, cuda_stream_view stream)

分配至少 bytes 大小的内存。

返回的指针将至少具有 256 字节对齐。

抛出:

rmm::bad_alloc – 当无法在指定 stream 上分配请求的 bytes 时。

参数:
  • bytes – 分配的大小

  • stream – 执行分配的流

返回:

void* 指向新分配内存的指针

inline void *deallocate_async(void *ptr, std::size_t bytes, std::size_t alignment, cuda_stream_view stream)

释放 p 指向的内存。

p 必须是由先前在与 *this 比较相等的 device_memory_resource 上调用 allocate(bytes, stream) 返回的,并且其指向的存储空间尚未被释放,否则行为未定义。

参数:
  • ptr – 要释放的指针

  • bytes – 分配的大小,以字节为单位。这必须等于返回 pallocate 调用中传递的 bytes 值。

  • alignment – 返回 pallocate 调用中传递的对齐方式

  • stream – 执行分配的流

inline void *deallocate_async(void *ptr, std::size_t bytes, cuda_stream_view stream)

释放 p 指向的内存。

p 必须是由先前在与 *this 比较相等的 device_memory_resource 上调用 allocate(bytes, stream) 返回的,并且其指向的存储空间尚未被释放,否则行为未定义。

参数:
  • ptr – 要释放的指针

  • bytes – 分配的大小,以字节为单位。这必须等于返回 pallocate 调用中传递的 bytes 值。

  • stream – 执行分配的流

inline bool operator==(device_memory_resource const &other) const noexcept

与另一个 device_memory_resource 的比较运算符。

参数:

other – 要比较的另一个资源

返回:

true 如果两个资源等效

返回:

false 如果两个资源不等效

inline bool operator!=(device_memory_resource const &other) const noexcept

与另一个 device_memory_resource 的比较运算符。

参数:

other – 要比较的另一个资源

返回:

false 如果两个资源等效

返回:

true 如果两个资源不等效

友元

inline friend void get_property(device_memory_resource const&, cuda::mr::device_accessible) noexcept

启用 cuda::mr::device_accessible 属性。

此属性声明 device_memory_resource 提供设备可访问的内存

template<typename Upstream>
class fixed_size_memory_resource : public detail::stream_ordered_memory_resource<fixed_size_memory_resource<Upstream>, detail::fixed_size_free_list>
#include <fixed_size_memory_resource.hpp>

一种 device_memory_resource,它分配单个固定大小的内存块。

仅支持小于配置的 block_size 的分配。

公共函数

inline explicit fixed_size_memory_resource(device_async_resource_ref upstream_mr, std::size_t block_size = default_block_size, std::size_t blocks_to_preallocate = default_blocks_to_preallocate)

构造一个新的 fixed_size_memory_resource,它从 upstream_mr 分配内存。

当块池全部被分配时,通过从 upstream_mr 分配 blocks_to_preallocate 个更多块来扩大池。

参数:
  • upstream_mr – 用于为池分配块的 device_async_resource_ref。

  • block_size – 要分配的块大小。

  • blocks_to_preallocate – 初始化池要分配的块数。

inline explicit fixed_size_memory_resource(Upstream *upstream_mr, std::size_t block_size = default_block_size, std::size_t blocks_to_preallocate = default_blocks_to_preallocate)

构造一个新的 fixed_size_memory_resource,它从 upstream_mr 分配内存。

当块池全部被分配时,通过从 upstream_mr 分配 blocks_to_preallocate 个更多块来扩大池。

参数:
  • upstream_mr – 用于为池分配块的 memory_resource。

  • block_size – 要分配的块大小。

  • blocks_to_preallocate – 初始化池要分配的块数。

inline ~fixed_size_memory_resource() override

销毁 fixed_size_memory_resource 并释放所有从上游分配的内存。

inline device_async_resource_ref get_upstream_resource() const noexcept

指向的上游资源的 device_async_resource_ref

返回:

指向的上游资源的 device_async_resource_ref

inline std::size_t get_block_size() const noexcept

获取此内存资源分配的块的大小。

返回:

已分配块的大小(字节),类型为 std::size_t。

公共静态属性

static constexpr std::size_t default_block_size = 1 << 20

默认分配块大小。

static constexpr std::size_t default_blocks_to_preallocate = 128

池最初拥有的块的数量,也是当其所有当前块都被分配完时,池增长的块的数量。

class managed_memory_resource : public rmm::mr::device_memory_resource
#include <managed_memory_resource.hpp>

device_memory_resource 派生类,使用 cudaMallocManaged/Free 进行分配/释放。

公共函数

managed_memory_resource(managed_memory_resource const&) = default

默认拷贝构造函数。

managed_memory_resource(managed_memory_resource&&) = default

默认移动构造函数。

managed_memory_resource &operator=(managed_memory_resource const&) = default

默认拷贝赋值运算符。

返回:

managed_memory_resource& 对赋值对象的引用

managed_memory_resource &operator=(managed_memory_resource&&) = default

默认移动赋值运算符。

返回:

managed_memory_resource& 对赋值对象的引用

template<typename T>
class polymorphic_allocator
#include <polymorphic_allocator.hpp>

一个使用 rmm::mr::device_memory_resource 执行(解)分配的流序 Allocator。

类似于 std::pmr::polymorphic_allocator,利用 device_memory_resource 的运行时多态性,允许将 polymorphic_allocator 作为静态分配器类型的容器可以互操作,但根据使用的资源表现出不同的行为。

与 STL 分配器不同,polymorphic_allocatorallocatedeallocate 函数是流序的。使用 stream_allocator_adaptor 允许与需要标准、非流序 `Allocator` 接口的接口进行互操作。

模板参数:

T – 分配器的值类型。

公共类型

using value_type = T

T,此分配器分配的对象的值类型。

公共函数

polymorphic_allocator() = default

使用 rmm::mr::get_current_device_resource_ref() 的返回值作为底层内存资源构造一个 polymorphic_allocator

inline polymorphic_allocator(device_async_resource_ref mr)

使用提供的内存资源构造一个 polymorphic_allocator

此构造函数提供了从 device_async_resource_ref 的隐式转换。

参数:

mr – 用于分配的上游内存资源。

template<typename U>
inline polymorphic_allocator(polymorphic_allocator<U> const &other) noexcept

使用 `other` 的底层内存资源构造一个 polymorphic_allocator

参数:

other – 其内存资源将用作新的 polymorphic_allocator 的底层资源的 polymorphic_allocator

inline value_type *allocate(std::size_t num, cuda_stream_view stream)

使用底层内存资源为 `num` 个类型为 `T` 的对象分配存储空间。

参数:
  • num – 要分配存储空间的对象数量

  • stream – 执行分配所在的流

返回:

指向已分配存储空间的指针

inline void deallocate(value_type *ptr, std::size_t num, cuda_stream_view stream)

释放 `ptr` 指向的存储空间。

`ptr` 必须是从一个内存资源 `r` 分配的,该资源使用 `r.allocate(n * sizeof(T))` 与 get_upstream_resource() 比较相等。

参数:
  • ptr – 指向要释放的内存的指针

  • num – 最初分配的对象数量

  • stream – 执行释放所在的流

inline rmm::device_async_resource_ref get_upstream_resource() const noexcept

rmm::device_async_resource_ref,指向(或引用)上游资源

返回:

rmm::device_async_resource_ref,指向(或引用)上游资源

template<typename Allocator>
class stream_allocator_adaptor
#include <polymorphic_allocator.hpp>

适配一个流序分配器以提供标准的 `Allocator` 接口。

流序分配器(即 `allocate/deallocate` 使用 cuda_stream_view)不能用于期望标准 C++ `Allocator` 接口的接口中。stream_allocator_adaptor 包装了一个流序分配器和一个流,以提供标准的 `Allocator` 接口。此适配器在调用底层分配器的 `allocate` 和 `deallocate` 函数时使用包装的流。

示例

my_stream_ordered_allocator<int> a{...};
cuda_stream_view s = // create stream;

auto adapted = stream_allocator_adaptor(a, s);

// Allocates storage for `n` int's on stream `s`
int * p = std::allocator_traits<decltype(adapted)>::allocate(adapted, n);

模板参数:

Allocator – 要适配的流序分配器类型

公共类型

using value_type = typename std::allocator_traits<Allocator>::value_type

此分配器分配的对象的值类型

公共函数

inline stream_allocator_adaptor(Allocator const &allocator, cuda_stream_view stream)

使用 `a` 作为底层分配器构造一个 stream_allocator_adaptor

注意

: 在 stream_allocator_adaptor 被销毁之前,`stream` 不能被销毁,否则行为是未定义的。

参数:
  • allocator – 用作底层分配器的流序分配器

  • stream – 与底层分配器一起使用的流

template<typename OtherAllocator>
inline stream_allocator_adaptor(stream_allocator_adaptor<OtherAllocator> const &other)

使用 `other.underlying_allocator()` 和 `other.stream()` 作为底层分配器和流构造一个 stream_allocator_adaptor

模板参数:

OtherAllocator – `other` 的底层分配器类型

参数:

other – 其底层分配器和流将被复制的另一个 stream_allocator_adaptor

inline value_type *allocate(std::size_t num)

stream() 上使用底层分配器为 `num` 个类型为 `T` 的对象分配存储空间。

参数:

num – 要分配存储空间的对象数量

返回:

指向已分配存储空间的指针

inline void deallocate(value_type *ptr, std::size_t num)

stream() 上使用底层分配器释放 `ptr` 指向的存储空间。

`ptr` 必须是由一个分配器 `a` 分配的,该分配器使用 `a.allocate(n)` 与 underlying_allocator() 比较相等。

参数:
  • ptr – 指向要释放的内存的指针

  • num – 最初分配的对象数量

inline cuda_stream_view stream() const noexcept

对底层分配器进行调用时所在的流。

返回:

对底层分配器进行调用时所在的流

inline Allocator underlying_allocator() const noexcept

底层分配器。

返回:

底层分配器

template<typename T>
struct rebind
#include <polymorphic_allocator.hpp>

将分配器重新绑定到指定的类型。

模板参数:

T – 重新绑定后的分配器类型所需的值类型 `value_type`

公共类型

using other = stream_allocator_adaptor<typename std::allocator_traits<Allocator>::template rebind_alloc<T>>

要绑定的类型。

template<typename Upstream>
class pool_memory_resource : public detail::maybe_remove_property<pool_memory_resource<Upstream>, Upstream, cuda::mr::device_accessible>, public detail::stream_ordered_memory_resource<pool_memory_resource<Upstream>, detail::coalescing_free_list>, public cuda::forward_property<pool_memory_resource<Upstream>, Upstream>
#include <pool_memory_resource.hpp>

一个合并式的最佳匹配子分配器,它使用从上游 `memory_resource` 分配的内存池。

分配 (do_allocate()) 和释放 (do_deallocate()) 是线程安全的。此外,此类与 CUDA 每线程默认流兼容。

模板参数:

UpstreamResource – 用于分配内存池的 `memory_resource`。实现了 rmm::mr::device_memory_resource 接口。

公共函数

inline explicit pool_memory_resource(device_async_resource_ref upstream_mr, std::size_t initial_pool_size, std::optional<std::size_t> maximum_pool_size = std::nullopt)

构造一个 pool_memory_resource 并使用 `upstream_mr` 分配初始设备内存池。

抛出:
  • rmm::logic_error – 如果 `initial_pool_size` 未按 pool_memory_resource::allocation_alignment 字节的倍数对齐。

  • rmm::logic_error – 如果 `maximum_pool_size` 既非默认值也未按 pool_memory_resource::allocation_alignment 字节的倍数对齐。

参数:
  • upstream_mr – 用于为池分配块的 memory_resource。

  • initial_pool_size – 初始池的最小大小(字节)。

  • maximum_pool_size – 池可以增长到的最大大小(字节)。默认为上游资源可用的所有内存。

inline explicit pool_memory_resource(Upstream *upstream_mr, std::size_t initial_pool_size, std::optional<std::size_t> maximum_pool_size = std::nullopt)

构造一个 pool_memory_resource 并使用 `upstream_mr` 分配初始设备内存池。

抛出:
  • rmm::logic_error – 如果 `upstream_mr == nullptr`

  • rmm::logic_error – 如果 `initial_pool_size` 未按 pool_memory_resource::allocation_alignment 字节的倍数对齐。

  • rmm::logic_error – 如果 `maximum_pool_size` 既非默认值也未按 pool_memory_resource::allocation_alignment 字节的倍数对齐。

参数:
  • upstream_mr – 用于为池分配块的 memory_resource。

  • initial_pool_size – 初始池的最小大小(字节)。

  • maximum_pool_size – 池可以增长到的最大大小(字节)。默认为上游资源可用的所有内存。

template<typename Upstream2 = Upstream, cuda::std::enable_if_t<cuda::mr::async_resource<Upstream2>, int> = 0>
inline explicit pool_memory_resource(Upstream2 &upstream_mr, std::size_t initial_pool_size, std::optional<std::size_t> maximum_pool_size = std::nullopt)

构造一个 pool_memory_resource 并使用 `upstream_mr` 分配初始设备内存池。

抛出:
  • rmm::logic_error – 如果 `upstream_mr == nullptr`

  • rmm::logic_error – 如果 `initial_pool_size` 未按 pool_memory_resource::allocation_alignment 字节的倍数对齐。

  • rmm::logic_error – 如果 `maximum_pool_size` 既非默认值也未按 pool_memory_resource::allocation_alignment 字节的倍数对齐。

参数:
  • upstream_mr – 用于为池分配块的 memory_resource。

  • initial_pool_size – 初始池的最小大小(字节)。

  • maximum_pool_size – 池可以增长到的最大大小(字节)。默认为上游资源可用的所有内存。

inline ~pool_memory_resource() override

销毁 pool_memory_resource 并使用上游资源释放其分配的所有内存。

inline device_async_resource_ref get_upstream_resource() const noexcept

rmm::device_async_resource_ref,指向(或引用)上游资源

返回:

rmm::device_async_resource_ref,指向(或引用)上游资源

inline std::size_t pool_size() const noexcept

计算当前内存池的大小。

包含已分配和空闲的内存。

返回:

std::size_t 当前已分配内存池的总大小。

class sam_headroom_memory_resource : public rmm::mr::device_memory_resource
#include <sam_headroom_memory_resource.hpp>

使用系统内存资源分配带预留空间的内存的资源。

系统分配内存(SAM)可以迁移到 GPU,但不会迁移回主机。如果 GPU 内存超额预订,这可能导致其他 CUDA 调用因内存不足而失败。为了解决这个问题,在使用系统内存资源时,我们预留一些 GPU 内存作为其他 CUDA 调用的预留空间,并且仅在分配不会占用预留空间时才将其首选位置条件性地设置为 GPU。

由于在每次分配时执行此检查可能开销很大,调用者可以选择使用其他分配器(例如 binning_memory_resource)进行小额分配,而仅对大额分配使用此分配器。

公共函数

inline explicit sam_headroom_memory_resource(std::size_t headroom)

构造一个预留空间内存资源。

参数:

headroom – 作为预留空间的预留 GPU 内存的大小

class system_memory_resource : public rmm::mr::device_memory_resource
#include <system_memory_resource.hpp>

使用 malloc/free 进行分配/释放的 device_memory_resource 派生类。

有两种硬件/软件环境支持从 GPU 访问系统分配内存(SAM):HMM 和 ATS。

异构内存管理 (HMM) 是针对 x86 系统上通过 PCIe 连接的 GPU 的基于软件的解决方案。要求

  • NVIDIA CUDA 12.2 以及开源 r535_00 驱动或更新版本。

  • 足够新的 Linux 内核:6.1.24+、6.2.11+ 或 6.3+。

  • 支持以下架构之一的 GPU:NVIDIA Turing、NVIDIA Ampere、NVIDIA Ada Lovelace、NVIDIA Hopper 或更新版本。

  • 64 位 x86 CPU。

更多信息,请参阅 https://developer.nvidia.com/blog/simplifying-gpu-application-development-with-heterogeneous-memory-management/。

地址转换服务 (ATS) 是 Grace Hopper Superchip 的硬件/软件解决方案,它使用 NVLink Chip-2-Chip (C2C) 互连提供一致性内存。更多信息,请参阅 https://developer.nvidia.com/blog/nvidia-grace-hopper-superchip-architecture-in-depth/。

公共函数

system_memory_resource(system_memory_resource const&) = default

默认拷贝构造函数。

system_memory_resource(system_memory_resource&&) = default

默认拷贝构造函数。

system_memory_resource &operator=(system_memory_resource const&) = default

默认拷贝赋值运算符。

返回:

system_memory_resource& 对赋值对象的引用

system_memory_resource &operator=(system_memory_resource&&) default

默认移动赋值运算符。

返回:

system_memory_resource& 对赋值对象的引用

group 主机内存资源
class host_memory_resource
#include <host_memory_resource.hpp>

主机内存分配的基类。

这基于 std::pmr::memory_resource:https://cppreference.cn/w/cpp/memory/memory_resource

当 C++17 可用于 RMM 时,`rmm::host_memory_resource` 应该继承自 `std::pmr::memory_resource`。

此类作为所有主机内存资源实现必须满足的接口。

所有派生类必须实现两个私有的纯虚函数:do_allocatedo_deallocate。可选地,派生类还可以重写 is_equal。默认情况下,is_equal 仅执行身份比较。

公共的非虚函数 allocatedeallocateis_equal 只是简单地调用私有虚函数。这样做的原因是允许在基类中实现共享的默认行为。例如,基类的 allocate 函数可能会记录每一次分配,无论使用哪种派生类实现。

子类包括 rmm::mr::new_delete_resource, rmm::mr::pinned_memory_resource

公共函数

host_memory_resource(host_memory_resource const&) = default

默认拷贝构造函数。

host_memory_resource(host_memory_resource&&) noexcept = default

默认移动构造函数。

host_memory_resource &operator=(host_memory_resource const&) = default

默认拷贝赋值运算符。

返回:

host_memory_resource& 对赋值对象的引用

host_memory_resource &operator=(host_memory_resource&&) noexcept = default

默认移动赋值运算符。

返回:

host_memory_resource& 对赋值对象的引用

inline void *allocate(std::size_t bytes, std::size_t alignment = alignof(std::max_align_t))

在主机上分配至少 `bytes` 字节大小的内存。

如果支持,返回的存储空间将按照指定的 `alignment` 对齐;否则,将按照 `alignof(std::max_align_t)` 对齐。

抛出:

std::bad_alloc – 当请求的 `bytes` 和 `alignment` 无法分配时。

参数:
  • bytes – 分配的大小

  • alignment – 分配的对齐方式

返回:

void* 指向新分配内存的指针

inline void deallocate(void *ptr, std::size_t bytes, std::size_t alignment = alignof(std::max_align_t))

释放 `ptr` 指向的内存。

`ptr` 必须是通过之前调用 `allocate(bytes,alignment)` 从一个与 `*this` 比较相等 host_memory_resource 返回的,并且其指向的存储空间尚未被释放,否则行为是未定义的。

参数:
  • ptr – 要释放的指针

  • bytes – 分配的大小(字节)。这必须等于返回 `ptr` 的 `allocate` 调用中传递的 `bytes` 值。

  • alignment – 分配的对齐方式。这必须等于返回 `ptr` 的 `allocate` 调用中传递的 `alignment` 值。

inline bool is_equal(host_memory_resource const &other) const noexcept

将此资源与另一个资源进行比较。

当且仅当从一个 host_memory_resource 分配的内存可以从另一个释放,反之亦然时,两个 host_memory_resource 比较相等。

默认情况下,仅检查 *thisother 是否指向同一对象,即不检查它们是否是同一类的两个对象。

参数:

other – 要比较的另一个资源

返回:

如果两个资源等价,则为 true

inline bool operator==(host_memory_resource const &other) const noexcept

与另一个 host_memory_resource 的比较运算符。

参数:

other – 要比较的另一个资源

返回:

true 如果两个资源等效

返回:

false 如果两个资源不等效

inline bool operator!=(host_memory_resource const &other) const noexcept

与另一个 host_memory_resource 的比较运算符。

参数:

other – 要比较的另一个资源

返回:

false 如果两个资源等效

返回:

true 如果两个资源不等效

友元

inline friend void get_property(host_memory_resource const&, cuda::mr::host_accessible) noexcept

启用 cuda::mr::host_accessible 属性。

此属性声明 host_memory_resource 提供主机可访问的内存。

class new_delete_resource : public rmm::mr::host_memory_resource
#include <new_delete_resource.hpp>

使用全局 `operator new` 和 `operator delete` 分配主机内存的 host_memory_resource

公共函数

new_delete_resource(new_delete_resource const&) = default

默认拷贝构造函数。

new_delete_resource(new_delete_resource&&) = default

默认移动构造函数。

new_delete_resource &operator=(new_delete_resource const&) = default

默认拷贝赋值运算符。

返回:

new_delete_resource& 对赋值对象的引用

new_delete_resource &operator=(new_delete_resource&&) default

默认移动赋值运算符。

返回:

new_delete_resource& 对赋值对象的引用

class pinned_memory_resource : public rmm::mr::host_memory_resource
#include <pinned_memory_resource.hpp>

使用 `cudaMallocHost` 分配固定/页锁定主机内存的 host_memory_resource

请参阅 https://devblogs.nvidia.com/how-optimize-data-transfers-cuda-cc/

公共函数

pinned_memory_resource(pinned_memory_resource const&) = default

默认拷贝构造函数。

pinned_memory_resource(pinned_memory_resource&&) = default

默认移动构造函数。

pinned_memory_resource &operator=(pinned_memory_resource const&) = default

默认拷贝赋值运算符。

返回:

pinned_memory_resource& 对被赋值对象的引用

pinned_memory_resource &operator=(pinned_memory_resource&&) = default

默认移动赋值运算符。

返回:

pinned_memory_resource& 对被赋值对象的引用

inline void *allocate_async(std::size_t bytes, std::size_t alignment, cuda_stream_view)

假装支持 allocate_async 接口,实际回退到 stream 0。

抛出:

rmm::bad_alloc – 当无法在指定 stream 上分配请求的 bytes 时。

参数:
  • bytes – 分配的大小

  • alignment – 分配所需的对齐方式

返回:

void* 指向新分配内存的指针

inline void *allocate_async(std::size_t bytes, cuda_stream_view)

假装支持 allocate_async 接口,实际回退到 stream 0。

抛出:

rmm::bad_alloc – 当无法在指定 stream 上分配请求的 bytes 时。

参数:

bytes – 分配的大小

返回:

void* 指向新分配内存的指针

inline void deallocate_async(void *ptr, std::size_t bytes, std::size_t alignment, cuda_stream_view)

假装支持 deallocate_async 接口,实际回退到 stream 0。

参数:
  • ptr – 要释放的指针

  • bytes – 分配的大小,以字节为单位。这必须等于返回 pallocate 调用中传递的 bytes 值。

  • alignment – 返回 pallocate 调用中传递的对齐方式

友元

inline friend void get_property(pinned_memory_resource const&, cuda::mr::device_accessible) noexcept

启用 cuda::mr::device_accessible 属性。

此属性声明 pinned_memory_resource 提供设备可访问的内存

group 设备资源适配器

类型别名

using failure_callback_t = std::function<bool(std::size_t, void*)>

failure_callback_resource_adaptor 使用的回调函数类型。

当内存分配抛出指定类型的异常时,资源适配器会调用此函数。函数决定资源适配器是应尝试再次分配内存还是重新抛出异常。

回调函数签名是:bool failure_callback_t(std::size_t bytes, void* callback_arg)

回调函数传递两个参数:bytes 是失败的内存分配大小,arg 是传递给 failure_callback_resource_adaptor 构造函数的额外参数。回调函数返回一个布尔值,其中 true 表示重试内存分配,false 表示重新抛出异常。

函数

template<template<typename...> class Resource, typename ...Upstreams, typename ...Args>
auto make_owning_wrapper(std::tuple<std::shared_ptr<Upstreams>...> upstreams, Args&&... args)

使用 upstreams 作为上游资源,并使用 args 作为构造 Resource 的额外参数,构造一个类型为 Resource 并包装在 owning_wrapper 中的资源。

template <typename Upstream1, typename Upstream2>
class example_resource{
  example_resource(Upstream1 * u1, Upstream2 * u2, int n, float f);
};

auto cuda_mr = std::make_shared<rmm::mr::cuda_memory_resource>();
auto cuda_upstreams = std::make_tuple(cuda_mr, cuda_mr);

// Constructs an `example_resource<rmm::mr::cuda_memory_resource, rmm::mr::cuda_memory_resource>`
// wrapped by an `owning_wrapper` taking shared ownership of `cuda_mr` and using it as both of
// `example_resource`s upstream resources. Forwards the  arguments `42` and `3.14` to the
// additional `n` and `f` arguments of `example_resource` constructor.
auto wrapped_example = rmm::mr::make_owning_wrapper<example_resource>(cuda_upstreams, 42, 3.14);
模板参数:
  • Resource – 指定要构造的包装资源的类型的模板模板参数

  • Upstreams – 上游资源的类型

  • Args – 在 Resource 的构造函数中使用的参数类型

参数:
  • upstreamsstd::shared_ptr 的元组,指向包装资源使用的上游,顺序与 Resource 的构造函数期望的顺序相同。

  • args – 要转发给包装资源的构造函数的函数参数包

返回:

一个 owning_wrapper,包装了一个新构造的 Resource<Upstreams...>upstreams

template<template<typename> class Resource, typename Upstream, typename ...Args>
auto make_owning_wrapper(std::shared_ptr<Upstream> upstream, Args&&... args)

Resource 只有一个上游资源时,owning_wrapper 的额外便利工厂函数。

当一个资源只有一个上游时,构造上游资源的 std::tuple 可能不方便。此工厂函数允许将单个上游指定为仅一个 std::shared_ptr

模板参数:
  • Resource – 要构造的包装资源的类型

  • Upstream – 单个上游资源的类型

  • Args – 在 Resource 的构造函数中使用的参数类型

参数:
  • upstream – 指向 上游资源的 std::shared_ptr

  • args – 要转发给包装资源的构造函数的函数参数包

返回:

一个 owning_wrapper,包装了一个新构造的 Resource<Upstream>upstream

template<typename Upstream>
class aligned_resource_adaptor : public rmm::mr::device_memory_resource
#include <aligned_resource_adaptor.hpp>

使 Upstream 内存资源以指定的对齐大小分配内存的资源。

此资源的一个实例可以使用现有的上游资源来构造,以满足分配请求。此适配器使用给定的对齐大小包装来自 Upstream 的分配和释放。

默认情况下,CUDA 驱动程序或运行时 API 的内存分配例程返回的任何地址始终至少对齐到 256 字节。对于某些用例,例如 GPUDirect Storage (GDS),为了避免额外的复制到 bounce buffer,分配需要对齐到更大的大小(GDS 为 4 KiB)。

由于更大的对齐大小会带来一些额外的开销,用户可以指定一个阈值大小。如果分配大小低于该阈值,则按默认大小对齐。只有大小超过阈值的分配才会按自定义对齐大小对齐。

模板参数:

Upstream – 用于分配/释放的上游资源的类型。

公共函数

inline explicit aligned_resource_adaptor(device_async_resource_ref upstream, std::size_t alignment = rmm::CUDA_ALLOCATION_ALIGNMENT, std::size_t alignment_threshold = default_alignment_threshold)

构造一个对齐资源适配器,使用 upstream 来满足分配请求。

抛出:

rmm::logic_error – 如果 allocation_alignment 不是 2 的幂

参数:
  • upstream – 用于分配/释放设备内存的资源。

  • alignment – 用于分配对齐的大小。

  • alignment_threshold – 只有大小大于或等于此阈值的分配才会被对齐。

inline explicit aligned_resource_adaptor(Upstream *upstream, std::size_t alignment = rmm::CUDA_ALLOCATION_ALIGNMENT, std::size_t alignment_threshold = default_alignment_threshold)

构造一个对齐资源适配器,使用 upstream 来满足分配请求。

抛出:
参数:
  • upstream – 用于分配/释放设备内存的资源。

  • alignment – 用于分配对齐的大小。

  • alignment_threshold – 只有大小大于或等于此阈值的分配才会被对齐。

inline rmm::device_async_resource_ref get_upstream_resource() const noexcept

rmm::device_async_resource_ref,指向(或引用)上游资源

返回:

rmm::device_async_resource_ref,指向(或引用)上游资源

公共静态属性

static constexpr std::size_t default_alignment_threshold = 0

适配器使用的默认对齐方式。

template<typename Upstream, typename ExceptionType = rmm::out_of_memory>
class failure_callback_resource_adaptor : public rmm::mr::device_memory_resource
#include <failure_callback_resource_adaptor.hpp>

一种设备内存资源,在分配抛出指定的异常类型时调用回调函数。

此资源的一个实例必须使用现有上游资源构造,以满足分配请求。

回调函数接受分配大小和回调参数,并返回一个布尔值,表示是否应重试分配 (true) 或重新抛出捕获到的异常 (false)。

在实现分配重试的回调函数时,必须注意避免无限循环。以下示例确保仅重试分配一次

using failure_callback_adaptor =
  rmm::mr::failure_callback_resource_adaptor<rmm::mr::device_memory_resource>;

bool failure_handler(std::size_t bytes, void* arg)
{
  bool& retried = *reinterpret_cast<bool*>(arg);
  if (!retried) {
    retried = true;
    return true;  // First time we request an allocation retry
  }
  return false;  // Second time we let the adaptor throw std::bad_alloc
}

int main()
{
  bool retried{false};
  failure_callback_adaptor mr{
    rmm::mr::get_current_device_resource_ref(), failure_handler, &retried
  };
  rmm::mr::set_current_device_resource_ref(mr);
}
模板参数:
  • Upstream – 用于分配/释放的上游资源的类型。

  • ExceptionType – 此适配器应响应的异常类型

公共类型

using exception_type = ExceptionType

此对象捕获/抛出的异常类型。

公共函数

inline failure_callback_resource_adaptor(device_async_resource_ref upstream, failure_callback_t callback, void *callback_arg)

构造一个新的 failure_callback_resource_adaptor,使用 upstream 来满足分配请求。

另请参阅

failure_callback_t

参数:
  • upstream – 用于分配/释放设备内存的资源

  • callback – 回调函数

  • callback_arg – 传递给 callback 的额外参数

inline failure_callback_resource_adaptor(Upstream *upstream, failure_callback_t callback, void *callback_arg)

构造一个新的 failure_callback_resource_adaptor,使用 upstream 来满足分配请求。

另请参阅

failure_callback_t

抛出:

rmm::logic_error – 如果 upstream == nullptr

参数:
  • upstream – 用于分配/释放设备内存的资源

  • callback – 回调函数

  • callback_arg – 传递给 callback 的额外参数

failure_callback_resource_adaptor(failure_callback_resource_adaptor&&) noexcept = default

默认移动构造函数。

failure_callback_resource_adaptor &operator=(failure_callback_resource_adaptor&&) noexcept = default

默认移动赋值运算符。

返回:

failure_callback_resource_adaptor& 对被赋值对象的引用

inline rmm::device_async_resource_ref get_upstream_resource() const noexcept

rmm::device_async_resource_ref,指向(或引用)上游资源

返回:

rmm::device_async_resource_ref,指向(或引用)上游资源

template<typename Upstream>
class limiting_resource_adaptor : public rmm::mr::device_memory_resource
#include <limiting_resource_adaptor.hpp>

使用 Upstream 分配内存并限制总分配量的资源。

此资源的一个实例可以使用现有的上游资源构造,以满足分配请求,但任何现有分配将不被跟踪。使用原子操作使此线程安全,但请注意,get_allocated_bytes 可能不包含正在进行的分配。

模板参数:

Upstream – 用于分配/释放的上游资源的类型。

公共函数

inline limiting_resource_adaptor(device_async_resource_ref upstream, std::size_t allocation_limit, std::size_t alignment = CUDA_ALLOCATION_ALIGNMENT)

构造一个新的限制资源适配器,使用 upstream 来满足分配请求,并限制总分配量。

参数:
  • upstream – 用于分配/释放设备内存的资源

  • allocation_limit – 此分配器允许的最大内存量

  • alignment – 每个分配缓冲区的起始地址的对齐字节数

inline limiting_resource_adaptor(Upstream *upstream, std::size_t allocation_limit, std::size_t alignment = CUDA_ALLOCATION_ALIGNMENT)

构造一个新的限制资源适配器,使用 upstream 来满足分配请求,并限制总分配量。

抛出:

rmm::logic_error – 如果 upstream == nullptr

参数:
  • upstream – 用于分配/释放设备内存的资源

  • allocation_limit – 此分配器允许的最大内存量

  • alignment – 每个分配缓冲区的起始地址的对齐字节数

limiting_resource_adaptor(limiting_resource_adaptor&&) noexcept = default

默认移动构造函数。

limiting_resource_adaptor &operator=(limiting_resource_adaptor&&) noexcept = default

默认移动赋值运算符。

返回:

limiting_resource_adaptor& 对被赋值对象的引用

inline device_async_resource_ref get_upstream_resource() const noexcept

指向的上游资源的 device_async_resource_ref

返回:

指向的上游资源的 device_async_resource_ref

inline std::size_t get_allocated_bytes() const

查询已分配的字节数。注意,这不能用于了解可能分配的大小,因为可能存在碎片以及此分配器未跟踪的内部页面大小和对齐。

返回:

std::size_t 已通过此分配器分配的字节数。

inline std::size_t get_allocation_limit() const

查询此分配器允许分配的最大字节数。这是对分配器的限制,而不是底层设备的表示。设备可能无法支持此限制。

返回:

std::size_t 此分配器允许的最大字节数

template<typename Upstream>
class logging_resource_adaptor : public rmm::mr::device_memory_resource
#include <logging_resource_adaptor.hpp>

使用 Upstream 分配内存并记录有关请求的分配/释放信息的资源。

此资源的一个实例可以使用现有的上游资源构造,以满足分配请求并记录分配/释放活动。

模板参数:

Upstream – 用于分配/释放的上游资源的类型。

公共函数

inline logging_resource_adaptor(Upstream *upstream, std::string const &filename = get_default_filename(), bool auto_flush = false)

构造一个新的日志资源适配器,使用 upstream 来满足分配请求,并将每个分配/释放的信息记录到 filename 指定的文件中。

日志文件将使用 CSV 格式写入。

如果 filename 已存在,则清除其内容。

创建多个具有相同 filenamelogging_resource_adaptor 将导致未定义行为。

抛出:
  • rmm::logic_error – 如果 upstream == nullptr

  • spdlog::spdlog_ex – 如果打开 filename 失败

参数:
  • upstream – 用于分配/释放设备内存的资源

  • filename – 写入日志信息的文件名。如果未指定,则从环境变量 “RMM_LOG_FILE” 中获取文件名。

  • auto_flush – 如果为 true,则每次分配/释放时都会刷新日志。警告:这会降低性能。

inline logging_resource_adaptor(Upstream *upstream, std::ostream &stream, bool auto_flush = false)

构造一个新的日志资源适配器,使用 upstream 来满足分配请求,并将每个分配/释放的信息记录到 stream 指定的 ostream。

日志文件将使用 CSV 格式写入。

抛出:

rmm::logic_error – 如果 upstream == nullptr

参数:
  • upstream – 用于分配/释放设备内存的资源

  • stream – 写入日志信息的 ostream。

  • auto_flush – 如果为 true,则每次分配/释放时都会刷新日志。警告:这会降低性能。

inline logging_resource_adaptor(Upstream *upstream, std::initializer_list<rapids_logger::sink_ptr> sinks, bool auto_flush = false)

构造一个新的日志资源适配器,使用 upstream 来满足分配请求,并将每个分配/释放的信息记录到 stream 指定的 ostream。

日志文件将使用 CSV 格式写入。

抛出:

rmm::logic_error – 如果 upstream == nullptr

参数:
  • upstream – 用于分配/释放设备内存的资源

  • sinks – 将日志输出写入的日志接收器列表。

  • auto_flush – 如果为 true,则每次分配/释放时都会刷新日志。警告:这会降低性能。

inline logging_resource_adaptor(device_async_resource_ref upstream, std::string const &filename = get_default_filename(), bool auto_flush = false)

构造一个新的日志资源适配器,使用 upstream 来满足分配请求,并将每个分配/释放的信息记录到 filename 指定的文件中。

日志文件将使用 CSV 格式写入。

如果 filename 已存在,则清除其内容。

创建多个具有相同 filenamelogging_resource_adaptor 将导致未定义行为。

抛出:

spdlog::spdlog_ex – 如果打开 filename 失败

参数:
  • upstream – 用于分配/释放设备内存的 resource_ref。

  • filename – 写入日志信息的文件名。如果未指定,则从环境变量 “RMM_LOG_FILE” 中获取文件名。

  • auto_flush – 如果为 true,则每次分配/释放时都会刷新日志。警告:这会降低性能。

inline logging_resource_adaptor(device_async_resource_ref upstream, std::ostream &stream, bool auto_flush = false)

构造一个新的日志资源适配器,使用 upstream 来满足分配请求,并将每个分配/释放的信息记录到 stream 指定的 ostream。

日志文件将使用 CSV 格式写入。

参数:
  • upstream – 用于分配/释放设备内存的 resource_ref。

  • stream – 写入日志信息的 ostream。

  • auto_flush – 如果为 true,则每次分配/释放时都会刷新日志。警告:这会降低性能。

inline logging_resource_adaptor(device_async_resource_ref upstream, std::initializer_list<rapids_logger::sink_ptr> sinks, bool auto_flush = false)

构造一个新的日志资源适配器,使用 upstream 来满足分配请求,并将每个分配/释放的信息记录到 stream 指定的 ostream。

日志文件将使用 CSV 格式写入。

参数:
  • upstream – 用于分配/释放设备内存的 resource_ref。

  • sinks – 将日志输出写入的日志接收器列表。

  • auto_flush – 如果为 true,则每次分配/释放时都会刷新日志。警告:这会降低性能。

logging_resource_adaptor(logging_resource_adaptor&&) noexcept = default

默认移动构造函数。

logging_resource_adaptor &operator=(logging_resource_adaptor&&) noexcept = default

默认移动赋值运算符。

返回:

logging_resource_adaptor& 对被赋值对象的引用

inline rmm::device_async_resource_ref get_upstream_resource() const noexcept

rmm::device_async_resource_ref,指向(或引用)上游资源

返回:

rmm::device_async_resource_ref,指向(或引用)上游资源

inline void flush()

刷新记录器内容。

inline std::string header() const

返回 CSV 头部字符串。

返回:

列名的 CSV 格式头部字符串

公共静态函数

static inline std::string get_default_filename()

返回环境变量 RMM_LOG_FILE 的值。

抛出:

rmm::logic_error – 如果未设置 RMM_LOG_FILE

返回:

RMM_LOG_FILE 的值,类型为 std::string

template<typename Resource, typename ...Upstreams>
class owning_wrapper : public rmm::mr::device_memory_resource
#include <owning_wrapper.hpp>

维护上游资源生命周期的资源适配器。

许多派生自 device_memory_resource 的类型从另一个“上游”资源分配内存。例如,pool_memory_resource 从上游资源分配其池。通常,资源不拥有其上游,因此用户有责任维护上游资源的生命周期。这可能很不方便且容易出错,特别是对于具有复杂上游资源(其自身也可能有上游)的资源。

owning_wrapper 通过 std::shared_ptr 共享所有上游资源的 ownership 来简化包装资源 wrapped 的生命周期管理。

为了方便起见,建议使用 make_owning_wrapper 工厂函数,而不是直接构造 owning_wrapper

示例

auto cuda = std::make_shared<rmm::mr::cuda_memory_resource>();
auto pool = rmm::mr::make_owning_wrapper<rmm::mr::pool_memory_resource>(cuda,initial_pool_size,
                                                                        max_pool_size);
// The `cuda` resource will be kept alive for the lifetime of `pool` and automatically be
// destroyed after `pool` is destroyed

模板参数:
  • Resource – 包装资源的类型

  • UpstreamsResource 使用的上游资源类型的模板参数包

公共类型

using upstream_tuple = std::tuple<std::shared_ptr<Upstreams>...>

上游内存资源的元组。

公共函数

template<typename ...Args>
inline owning_wrapper(upstream_tuple upstreams, Args&&... args)

使用提供的上游资源和转发给包装资源构造函数的任何额外参数来构造包装资源。

要求 Resource 具有一个构造函数,其第一个参数是其上游资源的原始指针,顺序与 upstreams 中的顺序相同,后跟与 args 中顺序相同的任何额外参数。

示例

template <typename Upstream1, typename Upstream2>
class example_resource{
  example_resource(Upstream1 * u1, Upstream2 * u2, int n, float f);
};

using cuda = rmm::mr::cuda_memory_resource;
using example = example_resource<cuda,cuda>;
using wrapped_example = rmm::mr::owning_wrapper<example, cuda, cuda>;
auto cuda_mr = std::make_shared<cuda>();

// Constructs an `example_resource` wrapped by an `owning_wrapper` taking shared ownership of
//`cuda_mr` and using it as both of `example_resource`s upstream resources. Forwards the
// arguments `42` and `3.14` to the additional `n` and `f` arguments of `example_resources`
// constructor.
wrapped_example w{std::make_tuple(cuda_mr,cuda_mr), 42, 3.14};

模板参数:

Args – 要转发到包装资源构造函数的模板参数包

参数:
  • upstreamsstd::shared_ptr 的元组,指向包装资源使用的上游,顺序与 Resource 的构造函数期望的顺序相同。

  • args – 要转发给包装资源的构造函数的函数参数包

inline Resource const &wrapped() const noexcept

对包装资源的常量引用。

返回:

对包装资源的常量引用

inline Resource &wrapped() noexcept

对包装资源的引用。

返回:

对包装资源的引用

template<typename Upstream>
class prefetch_resource_adaptor : public rmm::mr::device_memory_resource
#include <prefetch_resource_adaptor.hpp>

预取所有内存分配的资源。

模板参数:

Upstream – 用于分配/释放的上游资源的类型。

公共函数

inline prefetch_resource_adaptor(device_async_resource_ref upstream)

使用 upstream 构造新的预取资源适配器以满足分配请求。

参数:

upstream – 用于分配/释放设备内存的 `resource_ref`

inline prefetch_resource_adaptor(Upstream *upstream)

使用 upstream 构造新的预取资源适配器以满足分配请求。

抛出:

rmm::logic_error – 如果 upstream == nullptr

参数:

upstream – 用于分配/释放设备内存的资源

prefetch_resource_adaptor(prefetch_resource_adaptor&&) noexcept = default

默认移动构造函数。

prefetch_resource_adaptor &operator=(prefetch_resource_adaptor&&) noexcept = default

默认移动赋值运算符。

返回:

prefetch_resource_adaptor& 对分配的对象的引用

inline rmm::device_async_resource_ref get_upstream_resource() const noexcept

rmm::device_async_resource_ref,指向(或引用)上游资源

返回:

rmm::device_async_resource_ref,指向(或引用)上游资源

template<typename Upstream>
class statistics_resource_adaptor : public rmm::mr::device_memory_resource
#include <statistics_resource_adaptor.hpp>

使用 Upstream 分配内存并跟踪内存分配统计信息的资源。

可以使用现有的上游资源构造此资源的一个实例,以满足分配请求,但任何现有分配将不受跟踪。跟踪统计信息会存储内存资源的字节数和调用次数的当前、峰值和总分配内存量。

此资源支持嵌套统计信息,可以跟踪代码块的统计信息。使用 .push_counters() 开始跟踪代码块的统计信息,使用 .pop_counters() 停止跟踪。嵌套统计信息是层叠的,因此代码块跟踪的统计信息包括其所有跟踪的子代码块中跟踪的统计信息。

statistics_resource_adaptor 用作调试适配器,不应在性能敏感的代码中使用。

模板参数:

Upstream – 用于分配/释放的上游资源的类型。

公共类型

using read_lock_t = std::shared_lock<std::shared_mutex>

用于同步读访问的锁类型。

using write_lock_t = std::unique_lock<std::shared_mutex>

用于同步写访问的锁类型。

公共函数

inline statistics_resource_adaptor(device_async_resource_ref upstream)

使用 upstream 构造新的统计信息资源适配器以满足分配请求。

参数:

upstream – 用于分配/释放设备内存的 resource_ref。

inline statistics_resource_adaptor(Upstream *upstream)

使用 upstream 构造新的统计信息资源适配器以满足分配请求。

抛出:

rmm::logic_error – 如果 upstream == nullptr

参数:

upstream – 用于分配/释放设备内存的资源。

statistics_resource_adaptor(statistics_resource_adaptor&&) noexcept = default

默认移动构造函数。

statistics_resource_adaptor &operator=(statistics_resource_adaptor&&) noexcept = default

默认移动赋值运算符。

返回:

statistics_resource_adaptor& 对分配的对象的引用

inline rmm::device_async_resource_ref get_upstream_resource() const noexcept

rmm::device_async_resource_ref,指向(或引用)上游资源

返回:

rmm::device_async_resource_ref,指向(或引用)上游资源

inline counter get_bytes_counter() const noexcept

返回此适配器的 counter 结构体,其中包含自创建以来此适配器分配的字节数的当前、峰值和总数。

返回:

包含字节计数的 counter 结构体

inline counter get_allocations_counter() const noexcept

返回此适配器的 counter 结构体,其中包含自创建以来此适配器的分配次数的当前、峰值和总数。

返回:

包含分配计数的 counter 结构体

inline std::pair<counter, counter> push_counters()

在堆栈上推送一对零计数器,这将成为 get_bytes_counter()get_allocations_counter() 返回的新计数器。

返回:

推送之前堆栈中的顶部计数器对

inline std::pair<counter, counter> pop_counters()

从堆栈中弹出一对计数器。

抛出:

std::out_of_range – 如果计数器堆栈中的条目少于两个。

返回:

弹出之前堆栈中的顶部计数器对

struct counter
#include <statistics_resource_adaptor.hpp>

用于计数数字的当前值、峰值和总值的实用结构体。

公共函数

inline counter &operator+=(int64_t val)

val 添加到当前值,并在必要时更新峰值。

参数:

val – 要添加的值

返回:

对这个对象的引用

inline counter &operator-=(int64_t val)

从当前值中减去 val,并在必要时更新峰值。

参数:

val – 要减去的值

返回:

对这个对象的引用

inline void add_counters_from_tracked_sub_block(const counter &val)

val 添加到当前值,并在必要时更新峰值。

更新峰值时,我们假设 val 正在跟踪 this 跟踪的代码块内的代码块。由于嵌套统计信息是层叠的,我们必须将 val.peak 转换为如果它是 this 跟踪的统计信息的一部分时它会达到的峰值。我们通过加上 val 开始跟踪时活动的当前值来实现这一点,这样我们就可以得到 std::max(value + val.peak, peak)

参数:

val – 要添加的值

公共成员

int64_t value = {0}

当前值。

int64_t peak = {0}

value 的最大值

int64_t total = {0}

所有添加值的总和。

template<typename Upstream>
class thread_safe_resource_adaptor : public rmm::mr::device_memory_resource
#include <thread_safe_resource_adaptor.hpp>

Upstream 内存资源适配器调整为线程安全的资源。

可以使用现有的上游资源构造此资源的一个实例,以满足分配请求。此适配器将 Upstream 的分配和释放操作包装在互斥锁中。

模板参数:

Upstream – 用于分配/释放的上游资源的类型。

公共类型

using lock_t = std::lock_guard<std::mutex>

用于同步访问的锁类型。

公共函数

inline thread_safe_resource_adaptor(device_async_resource_ref upstream)

使用 upstream 构造新的线程安全资源适配器以满足分配请求。

所有分配和释放都受互斥锁保护

参数:

upstream – 用于分配/释放设备内存的资源。

inline thread_safe_resource_adaptor(Upstream *upstream)

使用 upstream 构造新的线程安全资源适配器以满足分配请求。

所有分配和释放都受互斥锁保护

抛出:

rmm::logic_error – 如果 upstream == nullptr

参数:

upstream – 用于分配/释放设备内存的资源。

inline rmm::device_async_resource_ref get_upstream_resource() const noexcept

rmm::device_async_resource_ref,指向(或引用)上游资源

返回:

rmm::device_async_resource_ref,指向(或引用)上游资源

template<typename T>
class thrust_allocator : public thrust::device_malloc_allocator<T>
#include <thrust_allocator_adaptor.hpp>

兼容 Thrust 容器和算法的 allocator,使用 device_async_resource_ref 进行内存分配/释放。

device_async_resource_ref 不同,thrust_allocator 是类型化的,绑定用于分配特定类型 T 的对象,但可以自由地重新绑定到其他类型。

该分配器记录当前的 cuda 设备,并且只能与对同一设备有效的底层 device_async_resource_ref 一起使用。

模板参数:

T – 此分配器将分配的对象的类型

公共类型

using Base = thrust::device_malloc_allocator<T>

此分配器的基类型。

using pointer = typename Base::pointer

指针类型。

using size_type = typename Base::size_type

大小类型。

公共函数

thrust_allocator() = default

默认构造函数使用默认内存资源和默认流创建分配器。

inline explicit thrust_allocator(cuda_stream_view stream)

使用默认设备内存资源和指定流构造 thrust_allocator

参数:

stream – 用于设备内存分配/释放的流

inline thrust_allocator(cuda_stream_view stream, rmm::device_async_resource_ref mr)

使用设备内存资源和流构造 thrust_allocator

参数:
  • mr – 用于设备内存分配的资源

  • stream – 用于设备内存分配/释放的流

template<typename U>
inline thrust_allocator(thrust_allocator<U> const &other)

复制构造函数。复制资源指针和流。

参数:

other – 要复制的 thrust_allocator

inline pointer allocate(size_type num)

分配类型 T 的对象

参数:

num – 要分配的类型 T 的元素数量

返回:

pointer 指向新分配存储的指针

inline void deallocate(pointer ptr, size_type num)

释放类型 T 的对象

参数:
  • ptr – 由先前对 allocate 的调用返回的指针

  • num – 元素数量,必须等于生成 p 的先前 allocate 调用传递的参数

inline rmm::device_async_resource_ref get_upstream_resource() const noexcept

rmm::device_async_resource_ref,指向(或引用)上游资源

返回:

rmm::device_async_resource_ref,指向(或引用)上游资源

inline cuda_stream_view stream() const noexcept

此分配器使用的流。

返回:

此分配器使用的流

友元

inline friend void get_property(thrust_allocator const&, cuda::mr::device_accessible) noexcept

启用 cuda::mr::device_accessible 属性。

此属性声明 thrust_allocator 提供设备可访问的内存

template<typename U>
struct rebind
#include <thrust_allocator_adaptor.hpp>

提供用另一种类型实例化的 thrust_allocator 的类型。

模板参数:

U – 用于实例化的另一种类型

公共类型

using other = thrust_allocator<U>

要绑定的类型。

template<typename Upstream>
class tracking_resource_adaptor : public rmm::mr::device_memory_resource
#include <tracking_resource_adaptor.hpp>

使用 Upstream 分配内存并跟踪分配的资源。

可以使用现有的上游资源构造此资源的一个实例,以满足分配请求,但任何现有分配将不受跟踪。如果 capture_stacks 为 true,跟踪会存储每个分配的大小和指针以及堆栈帧,因此可能会增加显著的开销。tracking_resource_adaptor 用作调试适配器,不应在性能敏感的代码中使用。请注意,除非项目与 -rdynamic 链接,否则调用堆栈可能不包含所有符号。这可以通过在 cmake 中使用 add_link_options(-rdynamic) 来实现。

模板参数:

Upstream – 用于分配/释放的上游资源的类型。

公共类型

using read_lock_t = std::shared_lock<std::shared_mutex>

用于同步读访问的锁类型。

using write_lock_t = std::unique_lock<std::shared_mutex>

用于同步写访问的锁类型。

公共函数

inline tracking_resource_adaptor(device_async_resource_ref upstream, bool capture_stacks = false)

使用 upstream 构造新的跟踪资源适配器以满足分配请求。

参数:
  • upstream – 用于分配/释放设备内存的资源

  • capture_stacks – 如果为 true,则捕获分配调用的堆栈

inline tracking_resource_adaptor(Upstream *upstream, bool capture_stacks = false)

使用 upstream 构造新的跟踪资源适配器以满足分配请求。

抛出:

rmm::logic_error – 如果 upstream == nullptr

参数:
  • upstream – 用于分配/释放设备内存的资源

  • capture_stacks – 如果为 true,则捕获分配调用的堆栈

tracking_resource_adaptor(tracking_resource_adaptor&&) noexcept = default

默认移动构造函数。

tracking_resource_adaptor &operator=(tracking_resource_adaptor&&) noexcept = default

默认移动赋值运算符。

返回:

tracking_resource_adaptor& 对分配的对象的引用

inline rmm::device_async_resource_ref get_upstream_resource() const noexcept

rmm::device_async_resource_ref,指向(或引用)上游资源

返回:

rmm::device_async_resource_ref,指向(或引用)上游资源

inline std::map<void*, allocation_info> const &get_outstanding_allocations() const noexcept

获取未完成分配映射。

返回:

一个 std::map<void*, allocation_info> const&,包含分配的映射。键是分配的内存指针,值是 allocation_info 结构体,其中包含大小以及(可能)堆栈跟踪。

inline std::size_t get_allocated_bytes() const noexcept

查询已分配的字节数。注意,这不能用于了解可能分配的大小,因为可能存在碎片以及此分配器未跟踪的内部页面大小和对齐。

返回:

std::size_t 已通过此分配器分配的字节数。

inline std::string get_outstanding_allocations_str() const

获取一个字符串,其中包含未完成分配的指针、它们的大小,以及可选地包含分配每个指针时的堆栈跟踪。

仅当此资源适配器使用 capture_stack == true 创建时,才包含堆栈跟踪。否则,未完成分配的指针将显示其大小和空堆栈跟踪。

返回:

std::string 包含未完成分配指针的字符串。

inline void log_outstanding_allocations() const

通过 RMM_LOG_DEBUG 记录任何未完成的分配。

struct allocation_info
#include <tracking_resource_adaptor.hpp>

关于分配存储的信息。包括大小,如果 tracking_resource_adaptor 初始化为捕获堆栈,则还包括堆栈跟踪。

公共函数

inline allocation_info(std::size_t size, bool capture_stack)

构造新的分配信息对象。

参数:
  • size – 分配的大小

  • capture_stack – 如果为 true,则捕获分配的堆栈跟踪

公共成员

std::unique_ptr<rmm::detail::stack_trace> strace

分配的堆栈跟踪。

std::size_t allocation_size

分配的大小。