3

我想使用 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;                                                  
}                     
4

2 回答 2

11

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

#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 vtoexclusive_scan而不是适当的迭代器v.begin()

对细节的关注是完成这项工作所缺乏的。它的工作原理:

$ 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指向向量第一个元素的 a。thrust::device_ptr.get()将返回一个原始设备指针。所以

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

thrust::copy(v, v+N, v_);

在这个例子中,它们在功能上是等效的。

于 2012-09-02T13:18:36.110 回答
3

将获得的原始指针转换cudaMalloc()thrust::device_ptrusing 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

于 2012-08-30T21:19:43.047 回答