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.).