Salut à tous !
Dernièrement je voulais paralléliser un traitement et en toute logique ai utilisé TParallel.For. Mais à l'utilisation le temps d'exécution me paraissait toujours très long (plus rapide évidemment mais toujours trop long à mon goût) ce qui m'étonnait.
J'ai donc codé une petit app de test et le résultat m'a plutôt surpris. Au démarrage j'ai bien le nombre de tâches égale au nombre de CPUs x2 (ce qui est prévu dans TParallel.For), soit 32 sur mon PC mais ça chute à 19 après 50% de traitement, puis à 3 (voire 2 comme ci-dessous !) à 90% avec pour conséquence que ces 10 derniers pourcents prennent 40 à 50% du temps total
Un test sur une VM 4 cœurs, et bien notre multi-tâches devient à terme du mono-tâche
Le résultat en image :
En rouge le nombre de tâches restantes (sur 300) et en bleu le nombre de tâches parallélisées. La liste à droite, pour info, est le nombre de tâches exécutées par cœur.
En augmentant le Stride à 10 (à quoi ça sert exactement, l'aide est plutôt laconique à ce sujet, voir ci-dessous) j'obtiens quelque chose de bien meilleur, 30 tâches du début à la fin. Chouette ! je reporte donc ça dans mon app et patatras ! les performances sont encore pires qu'avant !
Donc oui ce Stride peut augmenter les performances, encore faudrait-il savoir comment le définir.
Dans mon test le "travail" est un Sleep(1000) alors que dans mon app le traitement est plus rapide que ça, j'observe l'inverse de ce que dit l'aide.Le paramètre AStride vous permet de régler la performance. La boucle "parallel for" utilise un thread-pool pour planifier le travail. Si les paquets de travail sont très petits, la surcharge de synchronisation dans le thread-pool peut diminuer la performance. Si le paramètre AStride est supérieur à 1, alors les indices AStride sont regroupés dans une seule partie du travail. Cela réduit le temps dédié à la surcharge de synchronisation au détriment de la réduction du parallélisme dans la boucle.
Est-ce que quelqu'un aurait une idée de comment calculer cela ? Ou faut-il y aller par tâtonnement (sic) ?
Merci pour toute info. Si vous n'en avez pas, je reviendrai à une gestion multithreads à l'ancienne
ps: j'ai quant même de la peine à comprendre le concept ; TParallel.For est bloquant, le but est qu'il se termine le plus vite possible. Pourquoi limiter le nombre de cœurs utilisés ? Ça fait un peu penser à ces barres de progression qui affichent très vite 99% mais restent coincées dessus pendant des plombes...
Partager