C++ cuda推力系统中的多项更换

C++ cuda推力系统中的多项更换,c++,cuda,thrust,C++,Cuda,Thrust,我有一个设备向量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++中实现它的任何方法。我找到了一个可以一次替换单个元素的推力::替换。由于我需要替换大量数据,一次替换一个数据成为瓶颈。这可以通过先构建地图,

我有一个设备向量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++中实现它的任何方法。我找到了一个可以一次替换单个元素的推力::替换。由于我需要替换大量数据,一次替换一个数据成为瓶颈。

这可以通过先构建地图,然后应用查询地图的自定义函子来有效地完成

示例代码执行以下步骤:

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

  • 创建一个大小为
    最大元素
    的映射向量。在旧值的位置复制新值

  • mapper
    functor应用于
    A
    。此函子从映射向量中读取新值。如果此
    新值
    而非
    0
    ,则
    A
    中的值将替换为新值。这假定
    C
    永远不会包含
    0
    。如果它可以包含
    0
    ,则必须使用其他条件,例如,使用
    -1
    初始化映射向量,并检查
    是否为新值!=-1



  • A
    B
    的典型尺寸是什么?
    B
    是否仅包含3个值?@m.s.A可以包含范围内的值(如果为百万)。B和C的尺寸为
    #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