将thrust :: iterators转换为原始指针和从原始指针转换

时间:2012-08-30 16:30:05

标签: cuda thrust

我想使用Thrust库来计算CUDA中设备数组的前缀和。 我的数组分配了cudaMalloc()。我的要求如下:

main()  
{  
     Launch kernel 1 on data allocated through cudaMalloc()  
     // This kernel will poplulate some data d.  
     Use thrust to calculate prefix sum of d.  
     Launch kernel 2 on prefix sum.  
}

我想在我的内核之间的某处使用Thrust所以我需要方法将指针转换为设备迭代器并返回。下面的代码有什么问题?

int main()                                                        
{                                                                 
    int *a;                                                   
    cudaMalloc((void**)&a,N*sizeof(int));   
    thrust::device_ptr<int> d=thrust::device_pointer_cast(a);  
    thrust::device_vector<int> v(N);                    
    thrust::exclusive_scan(a,a+N,v);                          
    return 0;                                                  
}                     

2 个答案:

答案 0 :(得分:9)

最新编辑的完整工作示例如下所示:

#include <thrust/device_ptr.h>
#include <thrust/device_vector.h>
#include <thrust/scan.h>
#include <thrust/fill.h>
#include <thrust/copy.h>
#include <cstdio>

int main()                                                        
{                                                                 
    const int N = 16;
    int * a;
    cudaMalloc((void**)&a, N*sizeof(int));   
    thrust::device_ptr<int> d = thrust::device_pointer_cast(a);  
    thrust::fill(d, d+N, 2);
    thrust::device_vector<int> v(N);                    
    thrust::exclusive_scan(d, d+N, v.begin());

    int v_[N];
    thrust::copy(v.begin(), v.end(), v_);
    for(int i=0; i<N; i++)
        printf("%d %d\n", i, v_[i]);     

    return 0;                                                  
}

你错了:

  1. N未定义任何地方
  2. 将原始设备指针a而不是device_ptr d作为输入迭代器传递给exclusive_scan
  3. device_vector v传递给exclusive_scan而不是相应的迭代器v.begin()
  4. 注重细节是完成这项工作所缺乏的。它的工作原理是:

    $ nvcc -arch=sm_12 -o thrust_kivekset thrust_kivekset.cu 
    $ ./thrust_kivekset
    
    0 0
    1 2
    2 4
    3 6
    4 8
    5 10
    6 12
    7 14
    8 16
    9 18
    10 20
    11 22
    12 24
    13 26
    14 28
    15 30
    

    编辑:

    thrust::device_vector.data()将返回thrust::device_ptr,指向向量的第一个元素。 thrust::device_ptr.get()将返回原始设备指针。因此

    cudaMemcpy(v_, v.data().get(), N*sizeof(int), cudaMemcpyDeviceToHost);
    

    thrust::copy(v, v+N, v_);
    
    在这个例子中,

    在功能上是等效的。

答案 1 :(得分:3)

使用cudaMalloc()将从thrust::device_ptr获取的原始指针转换为thrust::device_pointer_cast。以下是Thrust文档中的一个示例:

#include <thrust/device_ptr.h>
#include <thrust/fill.h>
#include <cuda.h>

int main(void)
{
    size_t N = 10;

    // obtain raw pointer to device memory
    int * raw_ptr;
    cudaMalloc((void **) &raw_ptr, N * sizeof(int));

    // wrap raw pointer with a device_ptr 
    thrust::device_ptr<int> dev_ptr = thrust::device_pointer_cast(raw_ptr);

    // use device_ptr in Thrust algorithms
    thrust::fill(dev_ptr, dev_ptr + N, (int) 0);    

    // access device memory transparently through device_ptr
    dev_ptr[0] = 1;

    // free memory
    cudaFree(raw_ptr);

    return 0;
}

使用thrust::inclusive_scanthrust::exclusive_scan计算前缀总和。

http://code.google.com/p/thrust/wiki/QuickStartGuide#Prefix-Sums