c++ - cuda推力中的多项替换

标签 c++ cuda thrust

我有一个设备 vector A、B、C 如下。

A = [1,1,3,3,3,4,4,5,5]
B = [1,3,5]
C = [2,8,6]

所以我想用C中对应的元素替换a中的每个B。 例如:

  • 1 被 2 替换,
  • 3 被替换为 8,
  • 5 被 6 替换

从而得到如下结果

Result = [2,2,8,8,8,4,4,6,6]

我如何在cuda推力中实现这一点或在cuda C++中实现它的任何方式。我发现 Thrust::replace 可以一次替换单个元素。由于我需要替换大量数据,一次替换一个就成为瓶颈。

最佳答案

通过首先构建 map ,然后应用查询 map 的自定义仿函数,可以有效地完成此操作。

示例代码执行以下步骤:

  1. 获取C的最大元素。这假设您的数据已经排序。

  2. 创建大小为 largest_element 的 map vector 。将新值复制到旧值的位置。

  3. mapper仿函数应用于A。该仿函数从映射 vector 中读取new_value。如果此 new_value 不是 0,则 A 中的值将替换为新值。这假设 C 永远不会包含 0。如果它可以包含 0,则必须使用另一个条件,例如使用 -1 初始化 map vector 并检查是否 new_value != -1


#include <thrust/device_vector.h>
#include <thrust/iterator/permutation_iterator.h>
#include <thrust/copy.h>
#include <thrust/for_each.h>
#include <thrust/scatter.h>
#include <iostream>


#define PRINTER(name) print(#name, (name))
template <template <typename...> class V, typename T, typename ...Args>
void print(const char* name, const V<T,Args...> & v)
{
    std::cout << name << ":\t";
    thrust::copy(v.begin(), v.end(), std::ostream_iterator<T>(std::cout, "\t"));
    std::cout << std::endl;
}


template <typename T>
struct mapper
{
    mapper(thrust::device_ptr<const T> map) : map(map)
    {
    }

    __host__ __device__
    void operator()(T& value) const
    {
       const T& new_value = map[value]; 
       if (new_value)
       {
          value = new_value;
       }
    }

    thrust::device_ptr<const T> map;
};

int main()
{
    using namespace thrust::placeholders;

    int A[] = {1,1,3,3,3,4,4,5,5};
    int B[] = {1,3,5};
    int C[] = {2,8,6};

    int size_data    = sizeof(A)/sizeof(A[0]);
    int size_replace = sizeof(B)/sizeof(B[0]);

    // copy demo data to GPU
    thrust::device_vector<int> d_A (A, A+size_data);
    thrust::device_vector<int> d_B (B, B+size_replace);
    thrust::device_vector<int> d_C (C, C+size_replace);

    PRINTER(d_A);
    PRINTER(d_B);
    PRINTER(d_C);

    int largest_element = d_C.back();

    thrust::device_vector<int> d_map(largest_element);

    thrust::scatter(d_C.begin(), d_C.end(), d_B.begin(), d_map.begin());
    PRINTER(d_map);

    thrust::for_each(d_A.begin(), d_A.end(), mapper<int>(d_map.data()));
    PRINTER(d_A);

    return 0;
}

输出

d_A:    1   1   3   3   3   4   4   5   5   
d_B:    1   3   5   
d_C:    2   8   6   
d_map:  0   2   0   8   0   6   
d_A:    2   2   8   8   8   4   4   6   6   

关于c++ - cuda推力中的多项替换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31292634/

相关文章:

cuda - 设备内存上的推力减少结果

c++ - C或C++语言中的数组实际上是指针吗

c# - 无法使用 C# TCP 服务器和 C++ TCP 客户端接收消息

cuda - CUDA 常量内存的生命周期是多少?

cuda - 为什么 CUDA 对线程使用的寄存器数量进行四舍五入?

c++ - 命名空间 thrust::system::cuda::thrust 中无法解释的错误,特别是在 "system_error"和 "cuda_category"

c++ - 使用构造函数中本地声明的 device_vector 中的 device_vector::data() 方法初始化结构内部的指针是否安全?

c++ - Qt 槽不在多线程 DLL 中执行

C++ 比写入文本文件的 Bash 脚本快得多

Cuda 将常量从设备复制到主机