46

问题是:有没有办法在 Cuda 内核中使用类“向量”?当我尝试时,出现以下错误:

error : calling a host function("std::vector<int, std::allocator<int> > ::push_back") from a __device__/__global__ function not allowed

那么有没有办法在全局部分使用向量?我最近尝试了以下方法:

  1. 创建一个新的 Cuda 项目
  2. 转到项目的属性
  3. 打开 Cuda C/C++
  4. 转到设备
  5. 将“代码生成”中的值更改为该值:compute_20,sm_20

........之后,我可以在我的 Cuda 内核中使用 printf 标准库函数。

vector有没有办法以内核代码支持 printf 的方式使用标准库类?这是在内核代码中使用 printf 的示例:

// this code only to count the 3s in an array using Cuda
//private_count is an array to hold every thread's result separately 

__global__ void countKernel(int *a, int length, int* private_count) 
{
    printf("%d\n",threadIdx.x);  //it's print the thread id and it's working

    // vector<int> y;
    //y.push_back(0); is there a possibility to do this?

    unsigned int offset  = threadIdx.x * length;
    int i = offset;
    for( ; i < offset + length; i++)
    {
        if(a[i] == 3)
        {
            private_count[threadIdx.x]++;
            printf("%d ",a[i]);
        }
    }   
}
4

5 回答 5

21

你不能在 CUDA 中使用 STL,但你可以使用Thrust 库来做你想做的事。否则只需将向量的内容复制到设备并对其进行正常操作即可。

于 2012-04-29T20:47:34.070 回答
13

在 cuda 库推力中,可以使用thrust::device_vector<classT> 来定义设备上的向量,主机 STL 向量和设备向量之间的数据传输非常简单。你可以参考这个有用的链接:http ://docs.nvidia.com/cuda/thrust/index.html来找到一些有用的例子。

于 2013-05-03T16:02:31.687 回答
8

you can't use std::vector in device code, you should use array instead.

于 2012-04-30T12:58:53.663 回答
4

我认为您可以自己实现设备向量,因为 CUDA 支持设备代码中的动态内存分配。还支持运算符 new/delete。这是 CUDA 中设备向量的一个非常简单的原型,但它确实有效。它没有经过充分的测试。

template<typename T>
class LocalVector
{
private:
    T* m_begin;
    T* m_end;

    size_t capacity;
    size_t length;
    __device__ void expand() {
        capacity *= 2;
        size_t tempLength = (m_end - m_begin);
        T* tempBegin = new T[capacity];

        memcpy(tempBegin, m_begin, tempLength * sizeof(T));
        delete[] m_begin;
        m_begin = tempBegin;
        m_end = m_begin + tempLength;
        length = static_cast<size_t>(m_end - m_begin);
    }
public:
    __device__  explicit LocalVector() : length(0), capacity(16) {
        m_begin = new T[capacity];
        m_end = m_begin;
    }
    __device__ T& operator[] (unsigned int index) {
        return *(m_begin + index);//*(begin+index)
    }
    __device__ T* begin() {
        return m_begin;
    }
    __device__ T* end() {
        return m_end;
    }
    __device__ ~LocalVector()
    {
        delete[] m_begin;
        m_begin = nullptr;
    }

    __device__ void add(T t) {

        if ((m_end - m_begin) >= capacity) {
            expand();
        }

        new (m_end) T(t);
        m_end++;
        length++;
    }
    __device__ T pop() {
        T endElement = (*m_end);
        delete m_end;
        m_end--;
        return endElement;
    }

    __device__ size_t getSize() {
        return length;
    }
};
于 2017-08-14T09:23:34.527 回答
0

您不能std::vector在设备端代码中使用。为什么?

它没有标记为允许这样做

“正式”的原因是,要在设备端函数或内核中使用代码,代码本身必须在__device__函数中;而标准库中的代码,包括,std::vector不是。(constexpr代码有一个例外;在 C++20 中,std::vector确实有constexpr方法,但 CUDA 目前不支持 C++20,此外,这constexpr实际上是有限的。)

你可能真的不想

std::vector需要为您创建或添加到的向量增加存储空间时,该类使用分配器来获取更多内存。默认情况下(即,如果您使用std::vector<T>一些T) - 该分配是在堆上。虽然这可以适应 GPU - 如果每个“CUDA 线程”动态分配自己的内存,它会非常慢,而且速度非常慢。

#现在,你可以说“但我不想分配内存,我只想从向量中读取!” - 好吧,在这种情况下,您本身不需要向量。只需将数据复制到设备上的某个缓冲区,然后传递一个指针和一个大小,或者使用支持 CUDA 的跨度,例如在cuda-kat. 另一种选择,虽然有点“重”,是使用[NVIDIA推力库]的3 “设备向量”类。在引擎盖下,它与标准库向量完全不同。

于 2022-02-18T17:39:45.170 回答