Files
project_6/cccl_upstream/cub/cub/device/device_memcpy.cuh
EngineX CI 56fd68e7dd [INFRA] Import NVIDIA/CCCL upstream as optimization reference library
CCCL (CUDA C++ Core Libraries) provides:
- CUB: device/block/warp-level GPU primitives (reduce, scan, sort, topk)
- Thrust: high-level parallel algorithms (transform_reduce, sort, scan)
- libcudacxx: CUDA C++ standard library (atomics, barriers, memory)
- cudax: experimental features (memory resources, allocators)
- Tuning policies: per-SM hardware-specific algorithm parameters

Competition optimization vectors mapped to CCCL:
- Output TPS (83% weight): warp_reduce, block_reduce, device_topk
- Input TPS (14% weight): device_scan, block_load, prefetch
- Cache TPS (3% weight): prefix caching strategy patterns
- Memory (0.9 util): pooled/cached/buddy allocators

Source: https://github.com/NVIDIA/cccl (shallow clone, HEAD only)
License: Apache-2.0
2026-07-30 09:35:51 +00:00

294 lines
12 KiB
Plaintext

// SPDX-FileCopyrightText: Copyright (c) 2011-2022, NVIDIA CORPORATION. All rights reserved.
// SPDX-License-Identifier: BSD-3
//! @file
//! cub::DeviceMemcpy provides device-wide, parallel operations for copying data.
#pragma once
#include <cub/config.cuh>
#ifndef CCCL_DISABLE_NVRTC_COMPATIBILITY_CHECK
# if _CCCL_COMPILER(NVRTC)
# error \
"Including <cub/device/device_memcpy.cuh> is not supported when compiling with NVRTC. Include block-, warp-, or thread-level primitives instead (e.g. <cub/block/block_reduce.cuh>). You can define CCCL_DISABLE_NVRTC_COMPATIBILITY_CHECK to disable this warning."
# endif // _CCCL_COMPILER(NVRTC)
#endif // CCCL_DISABLE_NVRTC_COMPATIBILITY_CHECK
#if defined(_CCCL_IMPLICIT_SYSTEM_HEADER_GCC)
# pragma GCC system_header
#elif defined(_CCCL_IMPLICIT_SYSTEM_HEADER_CLANG)
# pragma clang system_header
#elif defined(_CCCL_IMPLICIT_SYSTEM_HEADER_MSVC)
# pragma system_header
#endif // no system header
#include <cub/detail/env_dispatch.cuh>
#include <cub/device/dispatch/dispatch_batch_memcpy.cuh>
#include <cuda/std/__execution/env.h>
#include <cuda/std/__type_traits/is_pointer.h>
#include <cuda/std/cstdint>
CUB_NAMESPACE_BEGIN
//! @brief cub::DeviceMemcpy provides device-wide, parallel operations for copying data.
//!
//! @rst
//!
//! Tuning
//! +++++++++++++++++++++++++++++++++++++++++++++
//!
//! All algorithms in DeviceMemcpy that accept an environment can be tuned by passing a custom :ref:`policy selector
//! <cub-policy-selectors>` that returns a :cpp:struct:`cub::BatchedCopyPolicy`, as shown in the example below:
//!
//! .. literalinclude:: ../../../cub/test/catch2_test_device_memcpy_env_api.cu
//! :language: c++
//! :dedent:
//! :start-after: example-begin memcpy-batched-policy-selector
//! :end-before: example-end memcpy-batched-policy-selector
//!
//! .. literalinclude:: ../../../cub/test/catch2_test_device_memcpy_env_api.cu
//! :language: c++
//! :dedent:
//! :start-after: example-begin memcpy-batched-tuning
//! :end-before: example-end memcpy-batched-tuning
//! @endrst
struct DeviceMemcpy
{
//! @rst
//! Copies data from a batch of given source buffers to their corresponding destination buffer.
//!
//! .. versionadded:: 2.2.0
//! First appears in CUDA Toolkit 12.3.
//!
//! .. note::
//!
//! If any input buffer aliases memory from any output buffer the behavior is undefined.
//! If any output buffer aliases memory of another output buffer the behavior is undefined.
//! Input buffers can alias one another.
//!
//! Snippet
//! +++++++
//!
//! The code snippet below illustrates usage of DeviceMemcpy::Batched for mutating strings withing
//! a single string buffer.
//!
//! .. code-block:: c++
//!
//! struct GetPtrToStringItem
//! {
//! __host__ __device__ __forceinline__ void *operator()(uint32_t index)
//! {
//! return &d_string_data_in[d_string_offsets[index]];
//! }
//! char *d_string_data_in;
//! uint32_t *d_string_offsets;
//! };
//!
//! struct GetStringItemSize
//! {
//! __host__ __device__ __forceinline__ uint32_t operator()(uint32_t index)
//! {
//! return d_string_offsets[index + 1] - d_string_offsets[index];
//! }
//! uint32_t *d_string_offsets;
//! };
//!
//! uint32_t num_strings = 5;
//! char *d_string_data_in; // e.g., "TomatoesBananasApplesOrangesGrapes"
//! char *d_string_data_out; // e.g., " ... "
//! uint32_t *d_string_offsets_old; // e.g., [0, 8, 15, 21, 28, 34]
//! uint32_t *d_string_offsets_new; // e.g., [0, 6, 13, 19, 26, 34]
//! uint32_t *d_gather_index; // e.g., [2, 1, 4, 3, 0]
//!
//! // Initialize an iterator that returns d_gather_index[i] when the i-th item is dereferenced
//! auto gather_iterator = thrust::make_permutation_iterator(thrust::make_counting_iterator(0),
//! d_gather_index);
//!
//! // Returns pointers to the input buffer for each string
//! auto str_ptrs_in = thrust::make_transform_iterator(gather_iterator,
//! GetPtrToStringItem{d_string_data_in,
//! d_string_offsets_old});
//!
//! // Returns the string size of the i-th string
//! auto str_sizes = thrust::make_transform_iterator(gather_iterator,
//! GetStringItemSize{d_string_offsets_old});
//!
//! // Returns pointers to the output buffer for each string
//! auto str_ptrs_out = thrust::make_transform_iterator(thrust::make_counting_iterator(0),
//! GetPtrToStringItem{d_string_data_out,
//! d_string_offsets_new});
//!
//! // Determine temporary device storage requirements
//! void *d_temp_storage = nullptr;
//! size_t temp_storage_bytes = 0;
//! cub::DeviceMemcpy::Batched(d_temp_storage, temp_storage_bytes, str_ptrs_in, str_ptrs_out,
//! str_sizes, num_strings);
//!
//! // Allocate temporary storage
//! cudaMalloc(&d_temp_storage, temp_storage_bytes);
//!
//! // Run batched copy algorithm (used to permute strings)
//! cub::DeviceMemcpy::Batched(d_temp_storage, temp_storage_bytes, str_ptrs_in, str_ptrs_out,
//! str_sizes, num_strings);
//!
//! // d_string_data_out <-- "ApplesBananasGrapesOrangesTomatoe"
//!
//! @endrst
//!
//! @tparam InputBufferIt
//! **[inferred]** Device-accessible random-access input iterator type providing the pointers to
//! the source memory buffers
//!
//! @tparam OutputBufferIt
//! **[inferred]** Device-accessible random-access input iterator type providing the pointers to
//! the destination memory buffers
//!
//! @tparam BufferSizeIteratorT
//! **[inferred]** Device-accessible random-access input iterator type providing the number of bytes
//! to be copied for each pair of buffers
//!
//! @param[in] d_temp_storage
//! @devicestorage
//!
//! @param[in,out] temp_storage_bytes
//! Reference to size in bytes of `d_temp_storage` allocation
//!
//! @param[in] input_buffer_it
//! Device-accessible iterator providing the pointers to the source memory buffers
//!
//! @param[in] output_buffer_it
//! Device-accessible iterator providing the pointers to the destination memory buffers
//!
//! @param[in] buffer_sizes
//! Device-accessible iterator providing the number of bytes to be copied for each pair of buffers
//!
//! @param[in] num_buffers
//! The total number of buffer pairs
//!
//! @param[in] stream
//! @rst
//! **[optional]** CUDA stream to launch kernels within. Default is stream\ :sub:`0`.
//! @endrst
template <typename InputBufferIt, typename OutputBufferIt, typename BufferSizeIteratorT>
CUB_RUNTIME_FUNCTION static cudaError_t Batched(
void* d_temp_storage,
size_t& temp_storage_bytes,
InputBufferIt input_buffer_it,
OutputBufferIt output_buffer_it,
BufferSizeIteratorT buffer_sizes,
::cuda::std::int64_t num_buffers,
cudaStream_t stream = nullptr)
{
_CCCL_NVTX_RANGE_SCOPE_IF(d_temp_storage, "cub::DeviceMemcpy::Batched");
static_assert(::cuda::std::is_pointer_v<cub::detail::it_value_t<InputBufferIt>>,
"DeviceMemcpy::Batched only supports copying of memory buffers."
"Please consider using DeviceCopy::Batched instead.");
static_assert(::cuda::std::is_pointer_v<cub::detail::it_value_t<OutputBufferIt>>,
"DeviceMemcpy::Batched only supports copying of memory buffers."
"Please consider using DeviceCopy::Batched instead.");
// Integer type large enough to hold any offset in [0, num_thread_blocks_launched), where a safe
// upper bound on num_thread_blocks_launched can be assumed to be given by
// IDIV_CEIL(num_buffers, 64)
using BlockOffsetT = uint32_t;
return detail::batch_memcpy::dispatch<CopyAlg::Memcpy, BlockOffsetT>(
d_temp_storage, temp_storage_bytes, input_buffer_it, output_buffer_it, buffer_sizes, num_buffers, stream);
}
//! @rst
//! Copies data from a batch of given source buffers to their corresponding destination buffer.
//!
//! .. versionadded:: 3.4.0
//! First appears in CUDA Toolkit 13.4.
//!
//! This is an environment-based API that allows customization of:
//!
//! - Stream: Query via ``cuda::get_stream``
//! - Memory resource: Query via ``cuda::mr::get_memory_resource``
//!
//! .. note::
//!
//! If any input buffer aliases memory from any output buffer the behavior is undefined.
//! If any output buffer aliases memory of another output buffer the behavior is undefined.
//! Input buffers can alias one another.
//!
//! Snippet
//! +++++++
//!
//! The code snippet below illustrates usage of DeviceMemcpy::Batched with an environment:
//!
//! .. literalinclude:: ../../../cub/test/catch2_test_device_memcpy_env_api.cu
//! :language: c++
//! :dedent:
//! :start-after: example-begin memcpy-batched-env
//! :end-before: example-end memcpy-batched-env
//!
//! @endrst
//!
//! @tparam InputBufferIt
//! **[inferred]** Device-accessible random-access input iterator type providing the pointers to
//! the source memory buffers
//!
//! @tparam OutputBufferIt
//! **[inferred]** Device-accessible random-access input iterator type providing the pointers to
//! the destination memory buffers
//!
//! @tparam BufferSizeIteratorT
//! **[inferred]** Device-accessible random-access input iterator type providing the number of bytes
//! to be copied for each pair of buffers
//!
//! @tparam EnvT
//! **[inferred]** Environment type (e.g., `cuda::std::execution::env<...>`)
//!
//! @param[in] input_buffer_it
//! Device-accessible iterator providing the pointers to the source memory buffers
//!
//! @param[in] output_buffer_it
//! Device-accessible iterator providing the pointers to the destination memory buffers
//!
//! @param[in] buffer_sizes
//! Device-accessible iterator providing the number of bytes to be copied for each pair of buffers
//!
//! @param[in] num_buffers
//! The total number of buffer pairs
//!
//! @param[in] env
//! @rst
//! **[optional]** Execution environment. Default is ``cuda::std::execution::env{}``.
//! @endrst
template <typename InputBufferIt,
typename OutputBufferIt,
typename BufferSizeIteratorT,
typename EnvT = ::cuda::std::execution::env<>,
::cuda::std::enable_if_t<!::cuda::std::is_same_v<InputBufferIt, void*>, int> = 0>
[[nodiscard]] CUB_RUNTIME_FUNCTION _CCCL_FORCEINLINE static cudaError_t
Batched(InputBufferIt input_buffer_it,
OutputBufferIt output_buffer_it,
BufferSizeIteratorT buffer_sizes,
::cuda::std::int64_t num_buffers,
const EnvT& env = {})
{
_CCCL_NVTX_RANGE_SCOPE("cub::DeviceMemcpy::Batched");
static_assert(::cuda::std::is_pointer_v<cub::detail::it_value_t<InputBufferIt>>,
"DeviceMemcpy::Batched only supports copying of memory buffers."
"Please consider using DeviceCopy::Batched instead.");
static_assert(::cuda::std::is_pointer_v<cub::detail::it_value_t<OutputBufferIt>>,
"DeviceMemcpy::Batched only supports copying of memory buffers."
"Please consider using DeviceCopy::Batched instead.");
using BlockOffsetT = uint32_t;
using default_policy_selector = detail::batch_memcpy::policy_selector;
return detail::dispatch_with_env_and_tuning<default_policy_selector>(
env, [&](auto policy_selector, void* storage, size_t& bytes, auto stream) {
return detail::batch_memcpy::dispatch<CopyAlg::Memcpy, BlockOffsetT>(
storage, bytes, input_buffer_it, output_buffer_it, buffer_sizes, num_buffers, stream, policy_selector);
});
}
};
CUB_NAMESPACE_END