j'essaye d'allouer la mémoire partagée en utilisant un paramètre constant mais en obtenant une erreur. mon noyau ressemble à ceci:
__global__ void Kernel(const int count)
{
__shared__ int a[count];
}
et je reçois une erreur disant
erreur: l'expression doit avoir une valeur constante
le comte est const! Pourquoi ai-je cette erreur? Et comment puis-je contourner cela?
const
ne signifie pas "constant", cela signifie "lecture seule".
Une expression constante est quelque chose dont la valeur est connue du compilateur au moment de la compilation.
CUDA prend en charge l'allocation dynamique de mémoire partagée. Si vous définissez le noyau comme ceci:
__global__ void Kernel(const int count)
{
extern __shared__ int a[];
}
puis passez le nombre d'octets requis comme troisième argument du lancement du noyau
Kernel<<< gridDim, blockDim, a_size >>>(count)
il peut ensuite être dimensionné au moment de l'exécution. Sachez que le runtime ne prend en charge qu'une seule allocation déclarée dynamiquement par bloc. Si vous en avez besoin de plus, vous devrez utiliser des pointeurs vers les décalages au sein de cette allocation unique. Sachez également que lorsque vous utilisez des pointeurs, la mémoire partagée utilise des mots de 32 bits et toutes les allocations doivent être alignées sur 32 bits, quel que soit le type d'allocation de mémoire partagée.
première option: déclarer la mémoire partagée avec une valeur constante (différente de const
)
__global__ void Kernel(int count_a, int count_b)
{
__shared__ int a[100];
__shared__ int b[4];
}
deuxième option: déclarer dynamiquement la mémoire partagée dans la configuration de lancement du noyau:
__global__ void Kernel(int count_a, int count_b)
{
extern __shared__ int *shared;
int *a = &shared[0]; //a is manually set at the beginning of shared
int *b = &shared[count_a]; //b is manually set at the end of a
}
sharedMemory = count_a*size(int) + size_b*size(int);
Kernel <<<numBlocks, threadsPerBlock, sharedMemory>>> (count_a, count_b);
note: Les pointeurs vers la mémoire partagée dynamiquement sont tous à la même adresse. J'utilise deux tableaux de mémoire partagée pour illustrer comment configurer manuellement deux tableaux en mémoire partagée.
Du "Guide de programmation CUDA C":
La configuration d'exécution est spécifiée en insérant une expression du formulaire:
<<<Dg, Db, Ns, S>>>
où:
Ainsi, en utilisant le paramètre dynamique Ns, l'utilisateur peut spécifier la taille totale de la mémoire partagée qu'une fonction de noyau peut utiliser, quel que soit le nombre de variables partagées qu'il y a dans ce noyau.
Vous ne pouvez pas déclarer une variable partagée comme celle-ci.
__shared__ int a[count];
bien que si vous êtes suffisamment sûr de la taille maximale d'un tableau, vous pouvez directement déclarer comme
__shared__ int a[100];
mais dans ce cas, vous devez vous inquiéter du nombre de blocs dans votre programme, car la fixation de la mémoire partagée sur un bloc (et sa non utilisation complète) vous conduira à un changement de contexte avec la mémoire globale (latence élevée), donc de mauvaises performances ...
Il existe une bonne solution à ce problème pour déclarer
extern __shared__ int a[];
et allouer la mémoire lors de l'appel du noyau à partir de la mémoire comme
Kernel<<< gridDim, blockDim, a_size >>>(count)
mais vous devriez également être dérangé ici, car si vous utilisez plus de mémoire dans les blocs que vous n'en affectez dans le noyau, vous obtiendrez des résultats inattendus.