7 votes

Synchronisations dans les GPU

J'ai quelques questions sur la façon dont les GPU effectuent les synchronisations. Comme je le sais, lorsqu'un warp rencontre une barrière (en supposant que ce soit en OpenCL), et qu'il sait que les autres warps du même groupe ne sont pas encore passés par là. Elle doit donc attendre. Mais que fait exactement ce warp pendant le temps d'attente ? Est-elle toujours active ? Ou va-t-elle effectuer des opérations nulles ?

Comme je le remarque, lorsque nous avons une synchronisation dans le noyau, le nombre d'instructions augmente. Je me demande quelle est la source de cet incrément. La synchronisation est-elle décomposée en autant de petites instructions GPU ? Ou parce que les warps inactifs exécutent quelques instructions supplémentaires ?

Et enfin, je me demande fortement si le coût ajouté par une synchronisation, par rapport à une synchronisation sans synchro, (disons barrière(CLK_LOCAL_MEM_FENCE)) est affecté par le nombre de chaîne dans un groupe de travail (ou threadblock) ? Merci

7voto

Tom Points 12285

Un warp actif est un warp qui réside sur le SM, c'est-à-dire que toutes les ressources (registres, etc.) ont été allouées et que le warp est disponible pour être exécuté, à condition qu'il soit planifiable. Si un warp atteint une barrière avant les autres warps du même threadblock/groupe de travail, il sera toujours actif (il réside toujours sur le SM et tous ses registres sont toujours valides), mais il n'exécutera aucune instruction puisqu'il n'est pas prêt à être ordonnancé.

L'insertion d'une barrière ne bloque pas seulement l'exécution mais agit également comme une barrière pour le compilateur : le compilateur n'est pas autorisé à effectuer la plupart des optimisations à travers la barrière car cela pourrait invalider le but de la barrière. C'est la raison la plus probable pour laquelle vous voyez plus d'instructions - sans la barrière, le compilateur est capable d'effectuer plus d'optimisations.

Le coût d'une barrière dépend beaucoup de ce que fait votre code, mais chaque barrière introduit une bulle où tous les warps doivent (effectivement) devenir inactifs avant de recommencer à travailler, donc si vous avez un très grand threadblock/groupe de travail, il y a bien sûr potentiellement une plus grande bulle qu'avec un petit bloc. L'impact de la bulle dépend de votre code - si votre code est très lié à la mémoire, la barrière exposera les latences de la mémoire là où elles étaient cachées auparavant, mais s'il est plus équilibré, l'effet sera moins perceptible.

Cela signifie que dans un noyau très limité en mémoire, il est préférable de lancer un plus grand nombre de petits blocs afin que d'autres blocs puissent être exécutés lorsqu'un bloc est en train de bouillonner sur une barrière. Vous devrez vous assurer que votre occupation augmente en conséquence, et si vous partagez des données entre les threads en utilisant la mémoire partagée par bloc, il y a un compromis à faire.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X