Performances de boucle dans un shader

11

Je me demande quelle est la meilleure façon d'intégrer une fonction de boucle dynamique dans un shader?

Premièrement, il semble que les tableaux dynamiques ne soient pas possibles. Alors, est-il préférable de créer un tableau de taille maximale et de n'en remplir qu'une partie ou de définir des tableaux avec des tailles prédéfinies?

Alors, quelle est la meilleure façon d'itérer sur ce tableau?

Vaut-il mieux utiliser une boucle déroulée ou une boucle dynamique pour quelque chose entre 4 à 128 itérations? J'ai également vu qu'il est possible de le dérouler à un nombre maximum d'itérations prédéfini puis de l'arrêter avec une condition telle que if (i == myCurrentMaximumIterationNumber).

Tapis
la source
2
Qu'essayez-vous de faire avec le tableau et la boucle? Je demande parce que cela ressemble en quelque sorte à un problème XY pour moi. Étant donné que la meilleure façon d'utiliser les conditions et les boucles sur le GPU est de ne pas les utiliser, il existe peut-être des méthodes encore meilleures au lieu d'utiliser des tableaux et des boucles dans votre cas.
Nero
J'implémente un effet de diffusion sous-surface d'écran qui fonctionne actuellement. Mais j'ai quelques doutes sur la façon dont j'utilise le noyau en fonction des performances. J'ai choisi de faire une taille de tableau maximale et de remplir uniquement une partie et d'utiliser une boucle dynamique avec un nombre dynamique d'itérations qui est lié au contenu du tableau actuellement utilisé. Je pense qu'il y a des choses à faire ou à savoir lors de la programmation de shaders en fonction des performances par exemple. Et à mon avis, les boucles sont un sujet de performance courant qui pourrait suivre certaines règles et peut-être des "bonnes pratiques", mais je n'ai trouvé aucune bonne réponse à ce sujet.
MaT

Réponses:

6

Les compilateurs de shader sont extrêmement agressifs à propos du déroulement, car les premiers HW n'avaient souvent pas de contrôle de flux et le coût des HW plus récents peut varier. Si vous disposez d'une référence que vous testez activement et d'une gamme de matériel pertinent, essayez de voir ce qui se passe. Votre boucle dynamique se prête mieux à l'intervention du développeur qu'une boucle statique - mais le laisser au compilateur est toujours un bon conseil, sauf si vous disposez d'un benchmark. Avec une référence, l'exploration vaut la peine (et est amusante).

BTW, la plus grande perte avec une boucle dynamique sur un GPU est que les "threads" individuels dans un front d'onde / chaîne se termineront à des moments différents. Les threads qui s'arrêtent plus tard forcent tous ceux qui se terminent tôt à exécuter des NOP.

Les boucles imbriquées doivent être soigneusement réfléchies: j'ai implémenté un décodeur d'entropie basé sur des blocs qui encodait des séquences de zéros (pour une compression de type JPEG). L'implémentation naturelle consistait à décoder les pistes dans une boucle interne serrée - ce qui signifiait souvent qu'un seul thread progressait; en aplatissant la boucle et en testant explicitement dans chaque thread s'il décodait ou non un run, j'ai gardé tous les threads actifs dans la boucle de longueur fixe (les blocs décodés avaient tous la même taille). Si les threads étaient comme des threads CPU, le changement aurait été terrible, mais sur le GPU sur lequel je tournais, j'ai eu une augmentation de 6 fois les performances (ce qui était toujours terrible - il n'y avait pas assez de blocs pour occuper le GPU - mais c'était une preuve de concept).

Daniel M Gessel
la source