You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于CUDA Thrust的向量批量替换与交替合并高效实现方案咨询

CUDA Thrust高效实现两种元素操作方案

一、批量替换向量部分值

核心思路

利用Thrust的copy结合花式迭代器直接定位目标区域,比replace_copy_if更高效——因为不需要判断条件,直接精准覆盖目标位置,避免条件分支带来的性能损耗。

实现代码

根据你场景的固定比例(size(arr1)/size(arr2)=2)和批次规则,分两种情况实现:

1. 固定替换奇数批次(索引1batch、3batch起始)

#include <thrust/device_vector.h>
#include <thrust/copy.h>

void batch_replace_fixed(thrust::device_vector<int>& arr1, 
                         const thrust::device_vector<int>& arr2, 
                         int batch_size) {
    // 替换第一个目标段:arr1[batch_size ... batch_size*2-1]
    thrust::copy(arr2.begin(), arr2.begin() + batch_size, 
                 arr1.begin() + batch_size);
    // 替换第二个目标段:arr1[batch_size*3 ... batch_size*4-1]
    thrust::copy(arr2.begin() + batch_size, arr2.end(), 
                 arr1.begin() + batch_size*3);
}

2. 通用批次替换(支持任意批次索引)

如果需要动态指定要替换的批次,可通过计算目标起始索引,循环执行copy:

#include <thrust/device_vector.h>
#include <thrust/copy.h>
#include <vector>

void batch_replace_general(thrust::device_vector<int>& arr1, 
                           const thrust::device_vector<int>& arr2, 
                           int batch_size, 
                           const std::vector<int>& target_batches) {
    int arr2_offset = 0;
    for (int batch_idx : target_batches) {
        int arr1_start = batch_idx * batch_size;
        int copy_count = batch_size;
        // 确保不越界
        if (arr1_start + copy_count > arr1.size() || arr2_offset + copy_count > arr2.size()) {
            break;
        }
        thrust::copy(arr2.begin() + arr2_offset, 
                     arr2.begin() + arr2_offset + copy_count, 
                     arr1.begin() + arr1_start);
        arr2_offset += copy_count;
    }
}

性能说明

直接用copy比replace_copy_if更高效,因为后者需要对每个元素做条件判断,而copy是无分支的内存拷贝操作,完全利用Thrust的内存带宽优化。


二、按交替索引合并两个向量

核心思路

利用Thrust的连续内存拷贝或花式迭代器生成索引映射,避免逐元素判断,最大化并行效率。

实现代码

方案1:批次循环拷贝(小批次场景)

通过循环批量拷贝对应批次,逻辑直观且高效:

#include <thrust/device_vector.h>
#include <thrust/copy.h>

thrust::device_vector<int> alternate_merge(const thrust::device_vector<int>& arr1, 
                                           const thrust::device_vector<int>& arr2, 
                                           int batch_size) {
    int total_size = arr1.size() + arr2.size();
    thrust::device_vector<int> arr3(total_size);
    
    int num_batches = arr1.size() / batch_size;
    for (int i = 0; i < num_batches; ++i) {
        // 拷贝arr1的第i个批次到arr3的2*i*batch_size起始位置
        thrust::copy(arr1.begin() + i*batch_size, 
                     arr1.begin() + (i+1)*batch_size, 
                     arr3.begin() + 2*i*batch_size);
        // 拷贝arr2的第i个批次到arr3的(2*i+1)*batch_size起始位置
        thrust::copy(arr2.begin() + i*batch_size, 
                     arr2.begin() + (i+1)*batch_size, 
                     arr3.begin() + (2*i+1)*batch_size);
    }
    return arr3;
}

方案2:花式迭代器并行合并(大批次场景)

通过transform_iterator生成索引映射,一次性完成并行合并,避免CPU端循环开销:

#include <thrust/device_vector.h>
#include <thrust/copy.h>
#include <thrust/iterator/permutation_iterator.h>
#include <thrust/iterator/transform_iterator.h>
#include <thrust/functional.h>

struct arr1_merge_mapper {
    int batch_size;
    arr1_merge_mapper(int bs) : batch_size(bs) {}

    __host__ __device__
    int operator()(int idx) {
        int global_batch = idx / (2 * batch_size);
        int in_batch_pos = idx % (2 * batch_size);
        return global_batch * batch_size + in_batch_pos;
    }
};

struct arr2_merge_mapper {
    int batch_size;
    arr2_merge_mapper(int bs) : batch_size(bs) {}

    __host__ __device__
    int operator()(int idx) {
        int global_batch = idx / (2 * batch_size);
        int in_batch_pos = idx % (2 * batch_size);
        return global_batch * batch_size + (in_batch_pos - batch_size);
    }
};

struct arr1_filter {
    int batch_size;
    arr1_filter(int bs) : batch_size(bs) {}
    __host__ __device__ bool operator()(int idx) {
        return idx % (2 * batch_size) < batch_size;
    }
};

struct arr2_filter {
    int batch_size;
    arr2_filter(int bs) : batch_size(bs) {}
    __host__ __device__ bool operator()(int idx) {
        return idx % (2 * batch_size) >= batch_size;
    }
};

thrust::device_vector<int> alternate_merge_fancy(const thrust::device_vector<int>& arr1, 
                                                const thrust::device_vector<int>& arr2, 
                                                int batch_size) {
    int total_size = arr1.size() + arr2.size();
    thrust::device_vector<int> arr3(total_size);

    // 生成arr1的置换迭代器
    auto arr1_perm = thrust::make_permutation_iterator(
        arr1.begin(),
        thrust::make_transform_iterator(
            thrust::make_counting_iterator(0),
            arr1_merge_mapper(batch_size)
        )
    );

    // 生成arr2的置换迭代器
    auto arr2_perm = thrust::make_permutation_iterator(
        arr2.begin(),
        thrust::make_transform_iterator(
            thrust::make_counting_iterator(0),
            arr2_merge_mapper(batch_size)
        )
    );

    // 分别拷贝arr1和arr2的对应元素到目标位置
    thrust::copy_if(
        arr1_perm, arr1_perm + total_size,
        thrust::make_counting_iterator(0),
        arr3.begin(),
        arr1_filter(batch_size)
    );

    thrust::copy_if(
        arr2_perm, arr2_perm + total_size,
        thrust::make_counting_iterator(0),
        arr3.begin(),
        arr2_filter(batch_size)
    );

    return arr3;
}

性能说明

方案1的循环拷贝在批次数量不大时足够高效,因为每个copy都是连续内存操作,Thrust会自动优化为高带宽 memcpy。方案2适合大批次场景,完全并行化处理,避免CPU端循环开销。


内容的提问来源于stack exchange,提问作者Chris

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 19:40:08