复制分割#

group 分割

函数

std::vector<packed_table> contiguous_split(cudf::table_view const &input, std::vector<size_type> const &splits, rmm::cuda_stream_view stream = cudf::get_default_stream(), rmm::device_async_resource_ref mr = cudf::get_current_device_resource_ref())#

对一个 table_view 执行深度复制分割,将其分割为一个 packed_table 向量,其中每个 packed_table 为所有分割的列数据使用一个连续的内存块。

输出视图的内存被分配在一个单独的连续 rmm::device_buffer 中,并在 packed_table 中返回。没有顶层拥有表。

返回的 input 视图是根据一个索引向量构造的,该向量指示每个分割应该发生在哪里。如果 i=0,则返回的第 itable_view 被切片为 [0, splits[i]);如果 i 是最后一个视图,则切片为 [splits[i], input.size());否则切片为 [splits[i-1], splits[i]]

对于所有的 i,期望 splits[i] <= splits[i+1] <= input.size()。对于大小为 N 的 splits,输出中总是会有 N+1 个分割。

Example:
input:   [{10, 12, 14, 16, 18, 20, 22, 24, 26, 28},
          {50, 52, 54, 56, 58, 60, 62, 64, 66, 68}]
splits:  {2, 5, 9}
output:  [{{10, 12}, {14, 16, 18}, {20, 22, 24, 26}, {28}},
          {{50, 52}, {54, 56, 58}, {60, 62, 64, 66}, {68}}]

注意

调用者有责任确保返回的视图不会超出返回的 packed_tableall_data 字段中包含的被视图化的设备内存的生命周期。

抛出:
  • std::out_of_range – 如果 splits 的结束索引大于 input 的大小。

  • std::out_of_range – 当 splits 中的值不在范围 [0, input.size()) 内时。

  • std::invalid_argument – 当 splits 中的值“严格递减”时。

参数:
  • input – 要分割的表格视图

  • splits – 视图将被分割的索引向量

  • stream – 用于设备内存操作和内核启动的 CUDA 流

  • mr – 用于所有返回的设备分配的可选内存资源

返回:

splits 指定的 input 的请求视图集以及被视图化的内存缓冲区

packed_columns pack(cudf::table_view const &input, rmm::cuda_stream_view stream = cudf::get_default_stream(), rmm::device_async_resource_ref mr = cudf::get_current_device_resource_ref())#

table_view 深度复制到序列化的连续内存格式中。

table_view 复制的元数据被复制到一个主机字节向量中,table_view 的数据被复制到一个 device_buffer 中。将此函数的输出传递给 cudf::unpack 进行反序列化。

参数:
  • input – 要打包的表格视图

  • stream – 用于设备内存操作和内核启动的 CUDA 流

  • mr – 用于所有返回的设备分配的可选内存资源

返回:

packed_columns 一个结构体,包含分别存储在连续主机和设备内存中的序列化元数据和数据

std::vector<uint8_t> pack_metadata(table_view const &table, uint8_t const *contiguous_buffer, size_t buffer_size)#

生成用于打包存储在连续缓冲区中的表的元数据。

table_view 复制的元数据被复制到一个主机字节向量中,可用于构造 packed_columnspacked_table 结构体。调用者负责保证表中的所有列都指向 contiguous_buffer

参数:
  • table – 要打包的表格视图

  • contiguous_buffer – 一个包含由 table 中的列引用的数据的连续设备内存缓冲区

  • buffer_sizecontiguous_buffer 的大小

返回:

表示用于 unpack packed_columns 结构体的元数据的字节向量

table_view unpack(packed_columns const &input)#

反序列化 cudf::pack 的结果。

将序列化表的结果转换为 table_view,该视图指向存储在 input 中包含的连续设备缓冲区中的数据。

调用者有责任确保输出中的 table_view 不会超出输入中数据的生命周期。

此函数中不会分配新的设备内存。

参数:

input – 要反打包的packed columns

返回:

反打包的 table_view

table_view unpack(uint8_t const *metadata, uint8_t const *gpu_data)#

反序列化 cudf::pack 的结果。

将序列化表的结果转换为 table_view,该视图指向存储在 gpu_data 中包含的连续设备缓冲区中的数据,使用主机缓冲区 metadata 中包含的元数据。

调用者有责任确保输出中的 table_view 不会超出输入中数据的生命周期。

此函数中不会分配新的设备内存。

参数:
  • metadata – 由初始 pack() 调用产生的主机端元数据缓冲区

  • gpu_data – 存储将被结果 table_view 引用的数据的设备端连续缓冲区

返回:

反打包的 table_view

std::vector<column_view> split(column_view const &input, host_span<size_type const> splits, rmm::cuda_stream_view stream = cudf::get_default_stream())#

根据一组派生自预期分割的索引,将 column_view 分割为一组 column_view

返回的 input 视图是根据一个分割向量构造的,该向量指示分割应该发生在哪里。如果 i=0,则返回的第 icolumn_view 被切片为 [0, splits[i]);如果 i 是最后一个视图,则切片为 [splits[i], input.size());否则切片为 [splits[i-1], splits[i]]

对于所有的 i,期望 splits[i] <= splits[i+1] <= input.size()。对于大小为 N 的 splits,输出中总是会有 N+1 个分割。

Example:
input:   {10, 12, 14, 16, 18, 20, 22, 24, 26, 28}
splits:  {2, 5, 9}
output:  {{10, 12}, {14, 16, 18}, {20, 22, 24, 26}, {28}}

注意

调用者有责任确保返回的视图不会超出被视图化的设备内存的生命周期。

抛出:
  • std::out_of_range – 如果 splits 的结束索引大于 input 的大小。

  • std::out_of_range – 当 splits 中的值不在范围 [0, input.size()) 内时。

  • std::invalid_argument – 当 splits 中的值“严格递减”时。

参数:
  • input – 要分割的列视图

  • splits – 视图将被分割的索引

  • stream – 用于设备内存操作和内核启动的 CUDA 流

返回:

splits 指定的 input 的请求视图集

std::vector<column_view> split(column_view const &input, std::initializer_list<size_type> splits, rmm::cuda_stream_view stream = cudf::get_default_stream())#

根据一组派生自预期分割的索引,将 column_view 分割为一组 column_view

返回的 input 视图是根据一个分割向量构造的,该向量指示分割应该发生在哪里。如果 i=0,则返回的第 icolumn_view 被切片为 [0, splits[i]);如果 i 是最后一个视图,则切片为 [splits[i], input.size());否则切片为 [splits[i-1], splits[i]]

对于所有的 i,期望 splits[i] <= splits[i+1] <= input.size()。对于大小为 N 的 splits,输出中总是会有 N+1 个分割。

Example:
input:   {10, 12, 14, 16, 18, 20, 22, 24, 26, 28}
splits:  {2, 5, 9}
output:  {{10, 12}, {14, 16, 18}, {20, 22, 24, 26}, {28}}

注意

调用者有责任确保返回的视图不会超出被视图化的设备内存的生命周期。

抛出:
  • std::out_of_range – 如果 splits 的结束索引大于 input 的大小。

  • std::out_of_range – 当 splits 中的值不在范围 [0, input.size()) 内时。

  • std::invalid_argument – 当 splits 中的值“严格递减”时。

参数:
  • input – 要分割的列视图

  • splits – 视图将被分割的索引

  • stream – 用于设备内存操作和内核启动的 CUDA 流

返回:

splits 指定的 input 的请求视图集

std::vector<table_view> split(table_view const &input, host_span<size_type const> splits, rmm::cuda_stream_view stream = cudf::get_default_stream())#

根据一组派生自预期分割的索引,将 table_view 分割为一组 table_view

返回的 input 视图是根据一个分割向量构造的,该向量指示分割应该发生在哪里。如果 i=0,则返回的第 table_view 被切片为 [0, splits[i]);如果 i 是最后一个视图,则切片为 [splits[i], input.size());否则切片为 [splits[i-1], splits[i]]

对于所有的 i,期望 splits[i] <= splits[i+1] <= input.size()。对于大小为 N 的 splits,输出中总是会有 N+1 个分割。

Example:
input:   [{10, 12, 14, 16, 18, 20, 22, 24, 26, 28},
          {50, 52, 54, 56, 58, 60, 62, 64, 66, 68}]
splits:  {2, 5, 9}
output:  [{{10, 12}, {14, 16, 18}, {20, 22, 24, 26}, {28}},
          {{50, 52}, {54, 56, 58}, {60, 62, 64, 66}, {68}}]

注意

调用者有责任确保返回的视图不会超出被视图化的设备内存的生命周期。

抛出:
  • std::out_of_range – 如果 splits 的结束索引大于 input 的大小。

  • std::out_of_range – 当 splits 中的值不在范围 [0, input.size()) 内时。

  • std::invalid_argument – 当 splits 中的值“严格递减”时。

参数:
  • input – 要分割的表格视图

  • splits – 视图将被分割的索引

  • stream – 用于设备内存操作和内核启动的 CUDA 流

返回:

splits 指定的 input 的请求视图集

std::vector<table_view> split(table_view const &input, std::initializer_list<size_type> splits, rmm::cuda_stream_view stream = cudf::get_default_stream())#

根据一组派生自预期分割的索引,将 table_view 分割为一组 table_view

返回的 input 视图是根据一个分割向量构造的,该向量指示分割应该发生在哪里。如果 i=0,则返回的第 table_view 被切片为 [0, splits[i]);如果 i 是最后一个视图,则切片为 [splits[i], input.size());否则切片为 [splits[i-1], splits[i]]

对于所有的 i,期望 splits[i] <= splits[i+1] <= input.size()。对于大小为 N 的 splits,输出中总是会有 N+1 个分割。

Example:
input:   [{10, 12, 14, 16, 18, 20, 22, 24, 26, 28},
          {50, 52, 54, 56, 58, 60, 62, 64, 66, 68}]
splits:  {2, 5, 9}
output:  [{{10, 12}, {14, 16, 18}, {20, 22, 24, 26}, {28}},
          {{50, 52}, {54, 56, 58}, {60, 62, 64, 66}, {68}}]

注意

调用者有责任确保返回的视图不会超出被视图化的设备内存的生命周期。

抛出:
  • std::out_of_range – 如果 splits 的结束索引大于 input 的大小。

  • std::out_of_range – 当 splits 中的值不在范围 [0, input.size()) 内时。

  • std::invalid_argument – 当 splits 中的值“严格递减”时。

参数:
  • input – 要分割的表格视图

  • splits – 视图将被分割的索引

  • stream – 用于设备内存操作和内核启动的 CUDA 流

返回:

splits 指定的 input 的请求视图集

struct packed_columns#
#include <contiguous_split.hpp>

序列化格式的列数据。

包含列数组的数据,存储在两个连续缓冲区中:一个在主机端,包含表格元数据;一个在设备端,包含表格数据。

公共函数

inline packed_columns(std::unique_ptr<std::vector<uint8_t>> &&md, std::unique_ptr<rmm::device_buffer> &&gd)#

构造一个新的packed columns对象。

参数:
  • md – 主机端元数据缓冲区

  • gd – 设备端数据缓冲区

公共成员

std::unique_ptr<std::vector<uint8_t>> metadata#

主机端元数据缓冲区。

std::unique_ptr<rmm::device_buffer> gpu_data#

设备端数据缓冲区。

struct packed_table#
#include <contiguous_split.hpp>

cudf::contiguous_split 的结果。

由 contiguous_split 执行的分割操作产生的每个 table_view 都将被包装在 packed_table 中返回。此结构体中的 table_view 和内部 column_views 不由顶层 cudf::tablecudf::column 拥有。相反,其背后的内存和元数据由 data 字段拥有,并且位于一个连续的块中。

用户负责确保 table 或任何派生的 table_views 不会超出 data 所拥有内存的生命周期。

公共成员

cudf::table_view table#

cudf::contiguous_split 的结果 table_view

packed_columns data#

拥有的列数据。

class chunked_pack#
#include <contiguous_split.hpp>

使用用户提供的 user_buffer_size 大小的缓冲区,对输入的 table_view 执行分块“打包”操作。

此操作的目的是在 GPU 内存不足时以流式方式使用,旨在最小化小的 cudaMemcpy 调用次数以及跟踪与 cudf 表相关的所有元数据。由于内存限制,所有 thrust 和 scratch 内存分配仅使用传入的内存资源,而不是每个设备的内存资源。

此类定义了两个必须协同使用的方法来执行 chunked_pack:has_next 和 next。示例如下:

// Create a table_view
cudf::table_view tv = ...;

// Choose a memory resource (optional). This memory resource is used for scratch/thrust temporary
// data. In memory constrained cases, this can be used to set aside scratch memory
// for `chunked_pack` at the beginning of a program.
auto mr = cudf::get_current_device_resource_ref();

// Define a buffer size for each chunk: the larger the buffer is, the more SMs can be
// occupied by this algorithm.
//
// Internally, the GPU unit of work is a 1MB batch. When we instantiate `cudf::chunked_pack`,
// all the 1MB batches for the source table_view are computed up front. Additionally,
// chunked_pack calculates the number of iterations that are required to go through all those
// batches given a `user_buffer_size` buffer. The number of 1MB batches in each iteration (chunk)
// equals the number of CUDA blocks that will be used for the main kernel launch.
//
std::size_t user_buffer_size = 128*1024*1024;

auto chunked_packer = cudf::chunked_pack::create(tv, user_buffer_size, mr);

std::size_t host_offset = 0;
auto host_buffer = ...; // obtain a host buffer you would like to copy to

while (chunked_packer->has_next()) {
  // get a user buffer of size `user_buffer_size`
  cudf::device_span<uint8_t> user_buffer = ...;
  std::size_t bytes_copied = chunked_packer->next(user_buffer);

  // buffer will hold the contents of at most `user_buffer_size` bytes
  // of the contiguously packed input `table_view`. You are now free to copy
  // this memory somewhere else, for example, to host.
  cudaMemcpyAsync(
    host_buffer.data() + host_offset,
    user_buffer.data(),
    bytes_copied,
    cudaMemcpyDefault,
    stream);

  host_offset += bytes_copied;
}

公共函数

explicit chunked_pack(cudf::table_view const &input, std::size_t user_buffer_size, rmm::cuda_stream_view stream = cudf::get_default_stream(), rmm::device_async_resource_ref temp_mr = cudf::get_current_device_resource_ref())#

构造一个新的 chunked_pack 类。

参数:
  • input – 要打包的源 table_view

  • user_buffer_size – 在 next 时将传入的缓冲区大小(字节)。必须至少为 1MB

  • stream – 用于设备内存操作和内核启动的 CUDA 流

  • temp_mr – 仅用于临时和 scratch 分配的可选内存资源

~chunked_pack()#

将被实现为默认的析构函数。此处声明并定义是因为 contiguous_split_state 在此阶段不完整。

std::size_t get_total_contiguous_size() const#

获取连续打包的 table_view 的总大小。

返回:

所有块的总大小(字节)

bool has_next() const#

检查是否有剩余块待复制的函数。

返回:

如果还有剩余块待复制,则为 true,否则为 false

std::size_t next(cudf::device_span<uint8_t> const &user_buffer)#

将下一个块打包到 user_buffer 中。只要 has_next 返回 true,就应该调用此方法。如果在 has_next 为 false 时调用 next,将抛出异常。

抛出:
  • cudf::logic_error – 如果 user_buffer 的大小与构造时传入的 user_buffer_size 参数不同。

  • cudf::logic_error – 如果在所有块复制完成后调用。

参数:

user_buffer – 块的目标设备 span。此 span 的大小必须等于构造时传入的 user_buffer_size 参数。

返回:

写入到 user_buffer 的字节数(最多 user_buffer_size

std::unique_ptr<std::vector<uint8_t>> build_metadata() const#

为所有添加的列构建不透明元数据。

返回:

包含序列化列元数据的向量

公共静态函数

static std::unique_ptr<chunked_pack> create(cudf::table_view const &input, std::size_t user_buffer_size, rmm::cuda_stream_view stream = cudf::get_default_stream(), rmm::device_async_resource_ref temp_mr = cudf::get_current_device_resource_ref())#

创建一个 chunked_pack 实例,用于对 table_view“input”执行“打包”操作,其中 user_buffer_size 大小的缓冲区填充了整个操作的块。此操作可在 GPU 内存受限的情况下使用。

内存资源(temp_mr)可以是一个特殊的内存资源,用于在 GPU 内存不足时,将 scratch 和临时分配从一小部分保留的内存池中进行的情况。请注意,它默认为常规的 cuDF 每设备资源。

抛出:

cudf::logic_error – 当 user_buffer_size 小于 1MB 时。

参数:
  • input – 要打包的源 table_view

  • user_buffer_size – 在 next 时将传入的缓冲区大小(字节)。必须至少为 1MB

  • stream – 用于设备内存操作和内核启动的 CUDA 流

  • temp_mr – 仅用于临时和 scratch 分配的 RMM 内存资源

返回:

一个 chunked_pack 的 unique_ptr