通过CUDA推力查找关键点的出现次数和第一次出现的位置

通过CUDA推力查找关键点的出现次数和第一次出现的位置,cuda,thrust,Cuda,Thrust,假设我有一个键向量 thrust::device_vector<int> keys(10); keys[0] = 51; // -----> keys[1] = 51; keys[2] = 72; // -----> keys[3] = 72; keys[4] = 72; keys[5] = 103; //-----> keys[6] = 103; keys[7] = 504; // ------> keys[8] = 504 keys[9

假设我有一个键向量

thrust::device_vector<int> keys(10); 
keys[0] = 51; // -----> 
keys[1] = 51; 
keys[2] = 72; // -----> 
keys[3] = 72; 
keys[4] = 72; 
keys[5] = 103; //-----> 
keys[6] = 103; 
keys[7] = 504; // ------> 
keys[8] = 504 
keys[9] = 504 ; 
推力::设备向量键(10);
键[0]=51;//--->
键[1]=51;
键[2]=72;//--->
键[3]=72;
键[4]=72;
键[5]=103;//--->
键[6]=103;
键[7]=504;//--->
键[8]=504
键[9]=504;
我之前已经知道,在 这个向量。我想填充这两个设备阵列
pidx[4]
pnum[4]

  • pidx
    数组为我提供了 keys vector,即上面代码段中标记为
    --->
    的位置。因此,在这个例子中,我应该有
    pidx[4]={0,2,5,7}

  • pnum
    数组提供每个键的出现次数。所以,在这个例子中,我应该
    pnum[4]={2,3,2,3}


  • 如何使用CUDA推力执行上述操作

    这不是最佳解决方案,但我想不出更好的办法

    // Use `unique` to grab the distinct values
    thrust::device_vector<int> values(4);
    thrust::unique_copy( keys.begin(), keys.end(), values.begin() );
    
    // For each of the values use `count` to get the frequencies
    for ( int i = 4; i != 0; --i )
        pnum[i] = thrust::count( keys.begin(), keys.end(), values[i] );
    
    // Use prefix sum to get the indices
    thrust::exclusive_scan( pnum.begin(), pnum.end(), pidx.begin() );
    
    //使用'unique'获取不同的值
    推力:设备_矢量值(4);
    唯一拷贝(keys.begin(),keys.end(),values.begin());
    //对于每个值,使用'count'获取频率
    对于(int i=4;i!=0;--i)
    pnum[i]=推力::计数(keys.begin()、keys.end()、值[i]);
    //使用前缀sum获取索引
    独占扫描(pnum.begin(),pnum.end(),pidx.begin());
    
    此解决方案假定您的密钥列表已排序。如果不是,那么只需在开始处添加另一个步骤来对列表进行排序

    // generate a list of indices to correspond with the key array
    thrust::device_vector<int> values(numKeys);
    thrust::sequence(values.begin(), values.end());
    
    // perform an inclusive scan to determine the minimum index for each unique key
    thrust::equal_to<int> binaryPred;
    thrust::minimum<int> binaryOp;
    thrust::inclusive_scan_by_key(keys.begin(), keys.end(), values.begin(), values.begin(), binaryPred, binaryOp);
    
    // find the unique indices
    thrust::unique(values.begin(), values.end());
    
    //生成与键数组相对应的索引列表
    推力:装置矢量值(numKeys);
    序列(values.begin(),values.end());
    //执行包含式扫描以确定每个唯一键的最小索引
    推力:等于二进制pred;
    推力:最小双星;
    推力::inclusive_按键扫描(keys.begin()、keys.end()、values.begin()、values.begin()、binaryPred、binaryOp);
    //找到唯一的索引
    唯一(values.begin(),values.end());
    
    作为替代解决方案,您可以尝试 图书馆。它具有针对此类问题的特殊功能:

       float keys[] = {51,51,72,72,72,103,103,504,504,504};      
       int N = sizeof(keys) / sizeof(int);
    
       array input(N, 1, keys);
       array values, pidx, locations;
       // unique elements in a vector and their indicies 
       setunique(values, pidx, locations, input);
    
       // # of unique elements
       int n_unique = pidx.elements();
       array pnum = zeros(n_unique); // empty array
    
       gfor(array i, n_unique) // parallel for loop
          // count the # of occurrences for each key
          pnum(i) = sum(locations == i);
    
       print(pidx);           
       print(pnum);
    
    输出:

    皮克斯= 0 2 5 7.0000

    pnum= 2 3 2
    3.0000

    您的问题涉及两个不同的问题:

  • 求向量内元素的发生次数
  • 查找每个关键点第一次出现的位置
  • 在我看来,上述两点在其他提供的答案中都没有得到承认

    问题#1在构建序列柱状图时涉及的金额,请参阅。这个问题的经典解决方案是,首先按
    推力::排序
    对键进行排序,然后执行
    推力::按_键减少
    ,以计算发生次数。这一点已在和中得到确认

    问题#2是按_键和
    推力::序列
    应用推力::唯一性

    下面是一个充分发挥作用的示例:

    #include <thrust/device_vector.h>
    #include <thrust/reduce.h>
    #include <thrust/random.h>
    #include <thrust/sort.h>
    
    /********/
    /* MAIN */
    /********/
    int main()
    {
        /**************************/
        /* SETTING UP THE PROBLEM */
        /**************************/
    
        const int N = 20;           // --- Number of elements
    
        // --- Random uniform integer distribution between 0 and 4
        thrust::default_random_engine rng;
        thrust::uniform_int_distribution<int> dist(0, 4);
    
        // --- Keys allocation and initialization
        thrust::device_vector<int> d_keys(N);
        for (size_t i = 0; i < d_keys.size(); i++) d_keys[i] = dist(rng);
    
        /****************/
        /* THE APPROACH */
        /****************/
    
        thrust::device_vector<int> d_values(N, 1);
        thrust::sort(d_keys.begin(), d_keys.end());
    
        thrust::reduce_by_key(d_keys.begin(), d_keys.end(), thrust::constant_iterator<int>(1), d_keys.begin(), d_values.begin());
    
        printf("Keys\n");
        for (int i=0; i<N; i++) std::cout << d_keys[i] << " " << d_values[i] << "\n";
        printf("\n");
    
        return 0;
    } 
    
    #包括
    #包括
    #包括
    #包括
    /********/
    /*主要*/
    /********/
    int main()
    {
    /**************************/
    /*设置问题*/
    /**************************/
    常数int N=20;/——元素数
    //---0和4之间的随机均匀整数分布
    推力:默认随机发动机转速;
    推力:均匀分布距离(0,4);
    //---密钥分配和初始化
    推力::设备矢量d_键(N);
    对于(size_t i=0;i