web-dev-qa-db-fra.com

Utilisation de std :: vector dans le code d'appareil CUDA

La question est la suivante: existe-t-il un moyen d'utiliser la classe "vector" dans les noyaux Cuda? Lorsque j'essaie, j'obtiens l'erreur suivante:

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

Donc, existe-t-il un moyen d'utiliser un vecteur dans la section globale? J'ai récemment essayé ce qui suit:

  1. créer un nouveau projet Cuda
  2. aller aux propriétés du projet
  3. ouvrir Cuda C/C++
  4. aller à l'appareil
  5. changez la valeur dans "Génération de code" à définir sur cette valeur: compute_20, sm_20

........ après cela, j'ai pu utiliser la fonction de bibliothèque standard printf dans mon noyau Cuda.

existe-t-il un moyen d'utiliser la classe de bibliothèque standard vector dans la façon dont printf est pris en charge dans le code du noyau? Voici un exemple d'utilisation de printf dans le code du noyau:

// 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]);
        }
    }   
}
37
Yasser

Vous ne pouvez pas utiliser la STL dans CUDA, mais vous pourrez peut-être utiliser la bibliothèque Thrust pour faire ce que vous voulez. Sinon, copiez simplement le contenu du vecteur sur l'appareil et utilisez-le normalement.

22
Edvard Pedersen

Dans la poussée de la bibliothèque cuda, vous pouvez utiliser thrust::device_vector<classT> pour définir un vecteur sur le périphérique, et le transfert de données entre le vecteur Host STL et le vecteur de périphérique est très simple. vous pouvez vous référer à ce lien utile: http://docs.nvidia.com/cuda/thrust/index.html pour trouver des exemples utiles.

14
Zhong Hu

vous ne pouvez pas utiliser std::vector dans le code du périphérique, vous devez utiliser un tableau à la place.

8
yyfn

Je pense que vous pouvez implémenter vous-même un vecteur de périphérique, car CUDA prend en charge l'allocation de mémoire dynamique dans les codes de périphérique. L'opérateur new/delete est également pris en charge. Voici un prototype extrêmement simple de vecteur de périphérique dans CUDA, mais cela fonctionne. Il n'a pas été suffisamment testé.

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;
    }
};
2
Robin Lew