将thrust :: 迭代器转换为原始指针,以及从原始指针转换为thrust :: 迭代器

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

1
这个编辑是想要提出一个新问题吗? - talonmies
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 作为输入迭代器传递给 exclusive_scan,而不是 device_ptr d
  3. device_vector v 传递给 exclusive_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_ptrthrust::device_ptr.get()将返回原始设备指针。因此:
cudaMemcpy(v_, v.data().get(), N*sizeof(int), cudaMemcpyDeviceToHost);

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

在此示例中,在功能上是等效的。


还有一件事,这样的错误弹出:thrust::system::system_error 在内存位置0x0043f3a8处。 - username_4567
看看我的编辑。已经基本上回答了您已经回答并接受的问题两次,也许应该投票。 - talonmies
我已经发布了一个演示,展示了代码编译和运行的正确性。正如我在你的另一个问题中所暗示的那样,你正在遇到ECC错误和其他症状,这表明可能是软件安装或硬件问题。 - talonmies

3

使用 thrust::device_pointer_cast 将从 cudaMalloc() 获取的原始指针转换为 thrust::device_ptr。以下是 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 来计算前缀和。
请参考快速开始指南中的前缀和章节

我尝试了,但对我没有用。我已经在问题中添加了源代码,请查看一下。 - username_4567

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接