Bien que la version efficace nécessite plus d'étapes, cela est compensé par le fait que le nombre de threads actifs diminue plus rapidement et que le nombre total de threads actifs sur toutes les itérations est considérablement plus petit. Si une chaîne n'a pas de threads actifs pendant une itération, cette chaîne passera simplement à la barrière suivante et sera suspendue, permettant aux autres chaînes de s'exécuter. Ainsi, avoir moins de chaînes actives peut souvent être rentable en temps d'exécution. (Cela implique implicitement que le code GPU doit être conçu de manière à ce que les threads actifs soient regroupés dans le moins de chaînes possible - vous ne voulez pas qu'ils soient dispersés de manière clairsemée, car même un thread actif forcera la chaîne entière pour rester actif.)
Considérez le nombre de threads actifs dans l'algorithme naïf. En regardant la figure 2 de l'article, vous pouvez voir que tous les threads sont actifs à l' exception des 2 premiers k sur la k ème itération. Donc, avec N threads, le nombre de threads actifs va comme N - 2 k . Par exemple, avec N = 1024, le nombre de threads actifs par itération est:
1023, 1022, 1020, 1016, 1008, 992, 960, 896, 768, 512
Si je le convertis en nombre de chaînes actives (en divisant par 32 et en arrondissant), j'obtiens:
32, 32, 32, 32, 32, 31, 30, 28, 24, 16
pour une somme de 289. D'un autre côté, l'algorithme efficace commence avec deux fois moins de threads, puis réduit de moitié le nombre de threads actifs à chaque itération jusqu'à ce qu'il descende à 1, puis commence à doubler jusqu'à ce qu'il revienne à la moitié de la taille du tableau à nouveau:
512, 256, 128, 64, 32, 16, 8, 4, 2, 1, 2, 4, 8, 16, 32, 64, 128, 256, 512
Conversion de ceci en chaînes actives:
16, 8, 4, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 4, 8, 16
La somme est de 71, ce qui n'est que le quart. Vous pouvez donc voir qu'au cours de toute l'opération, le nombre de chaînes actives est beaucoup plus petit avec l'algorithme efficace. (En fait, pour une longue course au milieu, il n'y a qu'une poignée de chaînes actives, ce qui signifie que la majeure partie de la puce n'est pas occupée. S'il y a des tâches de calcul supplémentaires en cours d'exécution, par exemple à partir d'autres flux CUDA, elles pourraient s'étendre pour remplir cette espace inoccupé.)