Boucles
La où les structures de controle de type if
et switch
permettent de sauter en aval (vars le “bas”) du programme
et d’ignorer des pans du code source, il existe des
structures de contrôle qui permettent de sauter en amont (vers
le “haut”) ce qui a pour effet de répéter les instructions
déjà effectuées.
Sauter ainsi vers le haut permet d’effectuer en écrivant peu de lignes de code des comportements répétitifs.
L’instruction while
exécutera le bloc d’instructions
qui le suit tant qu’une condition est valide, potentiellement
en l’exécutant jamais. L’instruction do/while
exécute également une instruction ou un bloc s’instructions
en boucle, mais le test est effectué après avoir exécuté
le bloc au moins une fois. l’instruction for
est taillée
pour exécuter un bloc un nombre déterminé de fois.
Performance et “parallélisation”
Comme toute structure de contrôle qui perturbe le flux
normal de l’exécution d’un programme, utiliser
une boucle peut avoir des effets négatifs sur la performance
et un compilateur essayera généralement d’applatir le
code source d’une boucle en “déroulant la boucle”, à moins
qu’un
flag de compilation
demandant de produire
un programme le plus petit possible est défini (-Osmall
).
C’est à dire que le programme
int main() {
char alph[] = {'a', 'b', 'c'};
for (int i = 0; i < 3 ; i++) {
putchar(alph[i]);
}
}
Une fois compilé ressemblera plutot à
int main() {
char alph[] = {'a', 'b', 'c'};
putchar(alph[0]);
putchar(alph[1]);
putchar(alph[2]);
}
Ce qui n’aura aucune incidence sur le comportement visible du programme tout en améliorant grandement sa performance.
Les problèmes de performance liées au boucles sont addressés de front dans les langage de shader en limitant leur grammaire pour garantir qu’une boucle pourra toujours être applatie (ou “déroulée”), notamment on ne peut pas accéder à la valeur d’un tableau via une adresse inconnue lors de la compilation, de modifier la valeur d’index au sein de la boucle ou modifier l’expression d’incrément de la boucle.
Vu qu’une carte graphique possède de nombreux registres et de coeurs, chaque traitement de boucle pourra être distribué (parralélisé).
Si on écrit du code pour le CPU (en langage C et non en shader donc) ces considérations valent la peine d’être connues et il vaut mieux en règle général garder les “boucles” de son code simples en sachant reconnaître ce qui peut empêcher un compilateur d’applatir une boucle (modifier la valeur de i au sein de la boucle, utiliser une valeur d’incrément non constante, écrire des corps de boucles trop volumineux, etc.).