繁体   English   中英

使用推力根据索引更改某些元素的值

[英]Change the values of some elements according to the index using thrust

  • 问题描述
    我想使用推力根据另一个索引数组设置数组中某些元素的值。 一个简单的例子如下所示:
// input:
int array[10] = {1,9,9,6,0,1,1,6,1,4};
int set_num = -1;
int index[4] = {0,2,4,6};
// output:
array[10] = {-1,9,-1,6,-1,1,-1,6,1,4};
  • 我的想法
    我不知道如何使用推力来完成它,所以我编写了自己的内核。 代码片段如下所示:
#include <cstdlib>
#include <iostream>
#include <cstdio>

#include "cuda_runtime.h"
#include "device_launch_parameters.h"


#include <thrust/host_vector.h>
#include <thrust/device_vector.h>
#include <thrust/execution_policy.h>
#include <thrust/copy.h>
#include <thrust/sequence.h>
#include <thrust/functional.h>

// kernel function
template <typename T>
__global__ void setNumInArray(T *arrays, int *index, T set_num, int num_index)
{
    unsigned int tid = threadIdx.x + blockDim.x * blockIdx.x;
    if (tid > num_index)
        return;
    arrays[index[tid]] = set_num;
}

int main()
{
    const unsigned int vec_length = 4069;                             // length of the array
    thrust::device_vector<int>vec(vec_length);
    thrust::sequence(thrust::device, vec.begin(), vec.end(), 1);      // the values are generated by thrust::sequence
    const int num_index = 16;                                         // length of the index array
    thrust::device_vector<int>index(num_index);                       // the index array is generated by thrust::sequence
    thrust::sequence(thrust::device, index.begin(), index.end(), 64,10);

    // type convert: thrust->normal device pointer
    int *d_vec = reinterpret_cast<int*>(thrust::raw_pointer_cast(vec.data()));
    int *d_index = reinterpret_cast<int*>(thrust::raw_pointer_cast(index.data()));

    int set_num = 0;    // the value I want to set

    int block_size = 64;
    setNumInArray<int> <<<1, block_size >>> (d_vec, d_index, set_num, num_index);

    thrust::host_vector<int>h_vec(vec_length);                         // check the result
    h_vec = vec;
    for (int ii = 0; ii < vec_length; ii++) {
        printf("%d: %d\n",ii+1,h_vec[ii]);
    }

    return 0;
}

这个程序可以输出正确的答案。 但是,我想避免推力变量和通用设备变量之间的类型转换(我在项目的另一部分使用了很多推力函数),也避免调整块/网格大小以获得更好的性能。 那么我怎样才能用推力实现它呢?

  • 工作环境
    • 操作系统:Windows10
    • 显卡:RTX2060
    • CUDA:10.2
    • IDE:VS2015
  • 其他问题
    1. 代码片段中我的类型转换方法是否正确? 它会导致一些潜在的问题吗?
    2. 为什么编译器(VS2015)找不到cudaOccupancyMaxPotentialBlockSizes 我想用它来确定最佳块大小。

您可以将推力::for_each 与 lambda 函数一起使用。 但是我没有对此进行基准测试,也许您的内核更快。

int main()
{
    const unsigned int vec_length = 4069;                        
    thrust::device_vector<int>vec(vec_length);
    thrust::sequence(thrust::device, vec.begin(), vec.end(), 1);     
    const int num_index = 16;                                         
    thrust::device_vector<int>index(num_index);                       
    thrust::sequence(thrust::device, index.begin(), index.end(), 64,10);
    int *d_vec = thrust::raw_pointer_cast(vec.data());
    int set_num = 0;

    auto changeValue = [=] __device__(int y) { d_vec[y] = set_num; };
    thrust::for_each(thrust::device, index.begin(), index.end(), changeValue);

    thrust::host_vector<int>h_vec(vec_length);
    h_vec = vec;
    for (int ii = 0; ii < vec_length; ii++) {
        if(h_vec[ii] == set_num)
            printf("%d: %d\n",ii+1,h_vec[ii]);
    }
    return 0;
}

这是使用“permutation_iterator”和“fill”的替代方法,我稍微编辑了eritjo的代码。

#include <thrust/device_vector.h>
#include <thrust/host_vector.h>
#include <thrust/execution_policy.h>
#include <thrust/sequence.h>
#include <thrust/functional.h>
#include <thrust/iterator/permutation_iterator.h>

int main()
{
    const unsigned int vec_length = 4069;                        
    thrust::device_vector<int>vec(vec_length);
    thrust::sequence(thrust::device, vec.begin(), vec.end(), 1);     
    const int num_index = 16;                                         
    thrust::device_vector<int>index(num_index);                       
    thrust::sequence(thrust::device, index.begin(), index.end(), 64,10);
    int set_num = 0;

    typedef thrust::device_vector<int>::iterator Iter;
    thrust::permutation_iterator<Iter, Iter> iter(vec.begin(), index.begin());
    thrust::fill(iter, iter+num_index, set_num);

    thrust::host_vector<int>h_vec(vec_length);
    h_vec = vec;

    for (int ii = 0; ii < vec_length; ii++) {
        if(h_vec[ii] == set_num)
            printf("%d: %d\n",ii+1,h_vec[ii]);
    }

    return 0;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM