2011-05-06 7 views
2

Je l'ai utilisé:manipulation de pointeur de périphérique CUDA

float *devptr; 
//... 
cudaMalloc(&devptr, sizeofarray); 
cudaMemcpy(devptr, hostptr, sizeofarray, cudaMemcpyHostToDevice); 

dans CUDA C pour allouer et remplir un tableau. Maintenant, je suis en train d'exécuter un noyau cuda, .: par exemple

__global__ void kernelname(float *ptr) 
{ 
    //... 
} 

dans ce tableau, mais avec une valeur de décalage. en C/C++, il serait someting comme ceci:

kernelname<<<dimGrid, dimBlock>>>(devptr+offset); 

Cependant, cela ne semble pas fonctionner.

Existe-t-il un moyen de le faire sans envoyer la valeur de décalage au noyau dans un argument séparé et utiliser ce décalage dans le code du noyau? Des idées sur la façon de faire cela?

Répondre

6

L'arithmétique de pointeur fonctionne très bien dans CUDA. Vous pouvez ajouter un décalage à un pointeur CUDA dans le code hôte et cela fonctionnera correctement (rappelez-vous que le décalage n'est pas un décalage d'octet, c'est un simple mot ou un décalage d'élément).

EDIT: Un exemple de travail simple:

#include <cstdio> 
int main(void) 
{ 

    const int na = 5, nb = 4; 
    float a[na] = { 1.2, 3.4, 5.6, 7.8, 9.0 }; 
    float *_a, b[nb]; 

    size_t sza = size_t(na) * sizeof(float); 
    size_t szb = size_t(nb) * sizeof(float); 

    cudaFree(0); 

    cudaMalloc((void **)&_a, sza); 
    cudaMemcpy(_a, a, sza, cudaMemcpyHostToDevice); 
    cudaMemcpy(b, _a+1, szb, cudaMemcpyDeviceToHost); 

    for(int i=0; i<nb; i++) 
     printf("%d %f\n", i, b[i]); 

    cudaThreadExit(); 
} 

Ici, vous pouvez voir un mot/élément décalage a été appliqué au pointeur de l'appareil dans le second cudaMemcpy appel pour démarrer la copie du deuxième mot, non la première.

+0

Merci pour la réponse. Je sais que ce n'est pas un décalage d'octets, cependant, je ne sais pas quelle est la taille d'un mot.J'ajoutais simplement le numéro d'index dont j'avais besoin du pointeur, comme je le fais en C++. Est-ce exact? – pmcr

+0

Peut-être que l'édition rend les choses un peu plus claires? – talonmies

+0

Nous vous remercions de votre temps. C'était très utile. Ça marche maintenant. C'était une erreur stupide. Je suis sincèrement désolé. – pmcr

1

L'arithmétique du pointeur fonctionne sur le code côté hôte, il est assez souvent utilisé dans le code fourni par nvidia.

"La mémoire linéaire existe sur le périphérique dans un espace d'adressage de 40 bits, de sorte que les entités affectées séparément peuvent se référencer les unes les autres via des pointeurs, par exemple, dans un arbre binaire."

En savoir plus sur: http://docs.nvidia.com/cuda/cuda-c-programming-guide/index.html#ixzz4KialMz00

et de la documentation des primitives de performance (NPP), un exemple parfait de l'arithmétique de pointeur.

« Select-canal 4.5.1 Source-Image pointeur Ceci est un pointeur sur le canal d'intérêt dans le premier pixel de l'image source. Par exemple, si PSRC est le pointeur au premier pixel à l'intérieur du retour sur investissement En utilisant la copie de canal select appropriée , on peut copier le deuxième canal de cette image source dans le premier canal d'une destination image donnée par pDst en décalant le pointeur de un: nppiCopy_8u_C3CR (pSrc + 1 , nSrcStep, pDst, nDstStep, oSizeROI); " * Note: cela fonctionne sans multiplier par le nombre d'octets par élément de données parce que le compilateur est conscient du type de données du pointeur, et calcule l'adresse en conséquence. En C et C++, l'arithmétique du pointeur peut être effectuée comme ci-dessus ou par la notation & ptr [offset] (pour renvoyer l'adresse de mémoire de l'unité au lieu de valeur, la valeur ne fonctionnera pas sur la mémoire du périphérique). Lors de l'utilisation de l'une ou l'autre des notations, la taille du type de données est gérée automatiquement et le décalage est spécifié en tant que nombre d'éléments de données plutôt que d'octets.

Questions connexes