CUDA détermination de threads par bloc, les blocs par grille
Je suis nouveau sur le CUDA de paradigme. Ma question est de déterminer le nombre de threads par bloc, et par blocs de la grille. Un peu d'art et d'essai de jouer dans ce processus? Ce que j'ai trouvé, c'est que de nombreux exemples l'ont apparemment nombre arbitraire choisie pour ces choses.
Je suis en train d'étudier un problème où je voudrais être en mesure de passer des matrices de toute taille à une méthode de multiplication. De sorte que, chaque élément de C (C = A * B) est calculé par un seul thread. Comment voulez-vous déterminer le fils de bloc, les blocs/grille dans ce cas?
Vous devez vous connecter pour publier un commentaire.
En général, vous souhaitez à la taille de vos blocs/grille pour correspondre à vos données et en même temps maximiser l'occupation, qui est, le nombre de threads actifs à la fois. Les principaux facteurs influençant l'occupation sont partagé l'utilisation de la mémoire, le registre de l'utilisation et du fil, de la taille du bloc.
Un CUDA GPU a sa capacité de traitement divisé en SMs (streaming multiprocesseurs), et le nombre de SMs dépend de la carte, mais ici nous allons nous concentrer sur une seule SM pour des raisons de simplicité (ils se comportent tous de la même façon). Chaque SM a un nombre fini de 32 bits des registres, la mémoire partagée, un nombre maximum d'actif blocs, ET d'un nombre maximum de threads actifs. Ces chiffres dépendent de la CC (compute capability) de votre GPU et peut être trouvé dans le milieu de l'article de Wikipédia http://en.wikipedia.org/wiki/CUDA.
Tout d'abord, votre fil de taille de bloc doit toujours être un multiple de 32, parce que les grains de donner des instructions dans les croisements (32 threads). Par exemple, si vous avez une taille de bloc de 50 threads, le GPU sera toujours émettre des commandes à 64 threads et vous devriez juste être en train de perdre leur.
Deuxième, avant de se soucier de la mémoire partagée et les registres, essayez de la taille de vos blocs basés sur le nombre maximum de threads et de blocs qui correspondent au calcul de la capacité de votre carte. Il y a parfois plusieurs façons de le faire... par exemple, un CC 3.0 de la carte de chaque SM pouvez avoir 16 active et de blocs de 2048 threads actifs. Cela signifie que si vous avez 128 threads par bloc, vous pourrait s'adapter à 16 pâtés de maisons de votre SM avant de frapper le 2048 limite de thread. Si vous utilisez 256 threads, vous pouvez seulement de 8, mais vous êtes toujours à l'aide de tous les threads disponibles et devront toujours pleine occupation. Cependant, l'utilisation de 64 threads par bloc de seulement utiliser 1024 threads lorsque le 16 block limite est atteint, de sorte que 50% d'occupation. Si la mémoire partagée et les enregistrer usage n'est pas un goulot d'étranglement, ce devrait être votre principale préoccupation (autres que vos données dimensions).
Sur le sujet de votre grille... les blocs de votre grille sont répartis sur les SMs pour commencer, et puis les autres blocs sont placés dans un pipeline. Les blocs sont déplacés dans le SMs pour le traitement dès qu'il y a assez de ressources que SM à prendre le bloc. En d'autres termes, comme des blocs de remplir un SM, de nouveaux sont arrivés. Vous pourriez faire l'argument que le fait d'avoir de plus petits blocs (128 au lieu de 256 dans l'exemple précédent) peut se terminer plus vite depuis un particulièrement lent bloc de porcs de moins de ressources, mais c'est très dépendant du code.
Ce qui concerne les registres et la mémoire partagée, regardez à la prochaine, car il se peut que la limitation de votre occupation. La mémoire partagée est fini pour l'ensemble de la SM, donc essayez de l'utiliser dans une quantité qui permet autant de blocs que possible afin de toujours s'adapter sur un SM. Il en va de même pour le registre. Encore une fois, ces chiffres dépendent de calcul de la capacité, et peut être trouvé exploités sur la page wikipedia. Bonne chance!
https://docs.nvidia.com/cuda/cuda-occupancy-calculator/index.html
À de rares exceptions près, vous devez utiliser un constant nombre de threads par bloc. Le nombre de blocs par grille est alors déterminée par la taille du problème, tels que la matrice de dimensions dans le cas de la multiplication de matrices.
Choisir le nombre de threads par bloc est très compliqué. La plupart des CUDA algorithmes admettre une large gamme de possibilités, et le choix est basé sur ce qui fait le noyau exécuter le plus efficacement possible. Il est presque toujours un multiple de 32, et au moins 64, car de la façon dont la planification de thread matériel fonctionne. Un bon choix pour une première tentative est de 128 ou 256.
Vous devez également tenir compte de la mémoire partagée, car les threads dans le même bloc peuvent accéder à la même mémoire partagée. Si vous êtes en train de concevoir quelque chose qui nécessite beaucoup de mémoire partagée, puis plus de threads par bloc peut être avantageux.
Par exemple, en termes de changement de contexte, d'un multiple de 32 fonctionne exactement de la même. Donc, pour le cas 1D, le lancement d'1 bloc avec 64 threads ou 2 blocs de 32 threads chacun fait aucune différence pour le mondial de l'accès à la mémoire. Toutefois, si le problème à la main naturellement se décompose en 1 longueur-64 vecteur, puis la première option sera mieux (moins de surcharge de mémoire, chaque thread peut accéder à la même mémoire partagée) que le second.