web-dev-qa-db-fra.com

allocation de mémoire partagée

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?

36
lina

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.

35

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.

84
talonmies

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.

20
jmilloy

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ù:

  • Dg est de type dim et spécifie la dimension et la taille de la grille ...
  • Db est de type dim et spécifie la dimension et la taille de chaque bloc ...
  • Ns est de type size_t et spécifie le nombre de octets dans la mémoire partagée qui est alloué dynamiquement par bloc pour cet appel en plus de l'allocation statique Mémoire. Cette mémoire allouée dynamiquement est utilisée par n'importe laquelle des variables déclarées comme un tableau externe comme mentionné dans __ shared __; Ns est un argument facultatif dont la valeur par défaut est 0;
  • S est de type cudaStream_t et spécifie le flux associé ...

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.

3
smh

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.

1
peeyush