是否可以在映射的数组上使用thrust :: device_ptr?

时间:2013-11-22 08:59:53

标签: cuda thrust

我试图在映射内存上使用thrust :: copy_if函数。但是,当我得到一个运行时错误并且我无法找到它时,在花费大量时间进行调试之前,我想确认它实际上是允许将指针传递给映射内存的事实push :: device_ptr包装器的位置。

这是我的意思的一个例子:

int size=1024;

int* v_locked;
int* v_device;
int* stencil_device;

device_ptr<int> v_wrapper;
device_ptr<int> v_wrapper_end;
device_ptr<int> stencil_wrapper;

cudaHostAlloc((void**)&v_locked, size*sizeof(int), cudaHostAllocMapped));
cudaHostGetDevicePointer(&v_device, &v_locked, 0);

cudaMalloc((void**)&stencil_device, size*sizeof(int));
/* 
kernel assigning stencil_device elements ...
*/

v_wrapper = device_pointer_cast(v_device);
stencil_wrapper = device_pointer_cast(stencil_device);

v_wrapper_end = copy_if(make_counting_iterator<int>(0), make_counting_iterator<int>(size), stencil_wrapper, v_wrapper, _1 == 1);

这是使用推力库的映射内存的正确用法吗?

谢谢。

1 个答案:

答案 0 :(得分:4)

是的,这是可能的。

我相信您的代码存在一些问题。

  1. 您似乎没有做任何proper cuda error checking如果您这样做,您会发现尽管您对cudaHostGetDevicePointer的调用似乎编译正确,但它们未正确设置。< / LI>
  2. 如上所述,您对cudaHostGetDevicePointer()的来电未正确设置。第二个指针参数作为单个指针(*)传递,而不是双指针(**)。请参阅documentation此编写的调用会抛出您可以捕获的cuda运行时错误。
  3. cudaHostAlloc来电之前,您应该使用对enable this featurecudaSetDeviceFlags(cudaDeviceMapHost);来电。
  4. 以下示例代码似乎对我有效,并修复了上述问题:

    $ cat t281.cu
    #include <iostream>
    #include <thrust/device_vector.h>
    #include <thrust/device_ptr.h>
    #include <thrust/copy.h>   
    
    #define cudaCheckErrors(msg) \
        do { \
            cudaError_t __err = cudaGetLastError(); \
            if (__err != cudaSuccess) { \
                fprintf(stderr, "Fatal error: %s (%s at %s:%d)\n", \
                    msg, cudaGetErrorString(__err), \
                    __FILE__, __LINE__); \
                fprintf(stderr, "*** FAILED - ABORTING\n"); \
                exit(1); \
            } \
        } while (0)
    
    template<typename T>
    struct is_one : thrust::unary_function<T, bool>
    {
        __host__ __device__
        bool operator()(const T &x)
        {
            return (x==1);
        }
    };
    
    int main(){
    
      int size=1024;
    
      int* v_locked;
      int* v_device;
      int* stencil_locked;
      int* stencil_device;
    
      cudaSetDeviceFlags(cudaDeviceMapHost);
      cudaCheckErrors("cudaSetDeviceFlags");
      cudaHostAlloc((void**)&v_locked, size*sizeof(int), cudaHostAllocMapped);
      cudaCheckErrors("cudaHostAlloc 1");
      cudaHostGetDevicePointer(&v_device, v_locked, 0);
      cudaCheckErrors("cudaHostGetDevicePointer 1");
      cudaHostAlloc((void**)&stencil_locked, size*sizeof(int), cudaHostAllocMapped);
      cudaCheckErrors("cudaHostAlloc 2");
      cudaHostGetDevicePointer(&stencil_device, stencil_locked, 0);
      cudaCheckErrors("cudaHostGetDevicePointer 2");
    
      for (int i = 0; i < size; i++){
        v_locked[i] = i;
        stencil_locked[i] = i%2;}
    
      thrust::device_ptr<int> v_wrapper = thrust::device_pointer_cast(v_device);
      thrust::device_ptr<int> stencil_wrapper = thrust::device_pointer_cast(stencil_device);
      thrust::device_ptr<int> v_wrapper_end = v_wrapper + size;
      thrust::device_vector<int> result(size);
      thrust::device_vector<int>::iterator result_end = copy_if(v_wrapper, v_wrapper_end, stencil_wrapper, result.begin(), is_one<int>());
      int result_size = result_end - result.begin();
      thrust::host_vector<int> h_result(result_size);
      thrust::copy_n(result.begin(), result_size, h_result.begin());
      thrust::copy_n(h_result.begin(), 10, std::ostream_iterator<int>(std::cout, " "));
      std::cout << std::endl;
      return 0;
    
    }
    $ nvcc -arch=sm_20 -o t281 t281.cu
    $ ./t281
    1 3 5 7 9 11 13 15 17 19
    $