Un grand nombre de ruisseaux dans C++ et efficacité

Actuellement j'ai écrit un programme dans la langue C++, qui utilise parfois plus 300 Fils. Dans mon programme, j'ai une gamme de structures et la longueur de la matrice est égale au nombre de flux. Supposons que j'ai 400 structures et donc, 400 Fils.

Par itération a for loop J'utilise la fonction pour chacun des 400 Les structures, et cette fonction est effectuée dans le flux. Donc j'ai 400 Fils fonctionnant en même temps.
/J'utilise la bibliothèque de flux boost/.

J'ai essayé de donner une ventilation de la façon dont mon code ressemble à /Ce n'est pas un vrai code./:


struct my_struct{
// Structure's members
};

std::vector<my_struct> my_vec;

void my_fun/my_struct* my_str/{
// Operations on my_str
}

int main//{
std::vector<boost::thread> thr/400/;
for /int k = 0; k &lt; 300; k++/{
for /int i = 0; i &lt; 400; i++/{
thr.at/i/ = boost::thread/my_fun, &amp;my_vec.at/i//;
}
}

for /int m = 0; m &lt; M; m++/{
thr.at/m/.join//;
}
}
}


La fonction que j'utilise est computionnellement intense et du code ci-dessus que j'utilise 400 Flux pour effectuer l'informatique, et cela est fait 300 temps. Y a-t-il un moyen plus efficace d'exécuter cette tâche? Je ne suis pas sûr que la présence de tels flux actifs puisse affecter simultanément la performance. J'ai entendu parler de la bibliothèque threadpool, Mais je ne suis pas sûr qu'elle m'apporte un avantage. Toute aide serait appréciée.

Merci beaucoup!.
</boost::thread></my_struct>
Invité:

Gaetan

Confirmation de:

Pas d'absence d'utilisation dans la création 400 Flux liés à la CPU, si vous n'avez pas 400 + Nuclei de processeur dans votre machine cible.

Il serait impossible de vous dire avec confiance comment il est préférable de distribuer votre charge de travail, de ne pas savoir quels calculs vous effectuez et sur les données.

En tant que tir dans le noir, à en juger par le fait que vous avez été publié, le premier coup utilisera
N

Flux /voir ci-dessous/ Et la séparation de la tienne 400 objets entre eux afin que chaque thread soit responsable du traitement approximativement
400/N

objets. Chaque thread peut effectuer un cycle. 300 Une fois et sur chaque itération, il peut gérer chacun des objets assignés.


N

- c'est un nombre arbitraire; En fait, je recommande d'essayer différentes valeurs et de comparer les résultats de la productivité. Cependant, si vos flux ne remplissent pas d'opérations d'E / S ou d'autres opérations qui passent du temps à bloquer les opérations non informatiques,
N

ne doit pas être plus que le nombre de noyaux de processeur dans votre voiture /Essayez de voir comment

Chute fréquemment

Votre productivité /.

Edit: Selon la discussion en cours, il serait souhaitable d'utiliser la file d'attente de vos objets à partir de laquelle chacun de vos flux.
N

Peut-être juste sauter quand ils sont prêts pour un travail supplémentaire. La file d'attente, bien sûr, devrait être du thread-coffre-fort. Pour une performance optimale, vous devez implémenter une file d'attente sans blocage.
http://people.csail.mit.edu/ed ... 4.pdf
Il y a un bon journal . La mise en œuvre devrait être simplifiée par le fait que vous remplissez complètement la file d'attente une fois et que vous n'avez donc besoin que de la lecture de fil-sécurité.

David

Confirmation de:

La seule façon dont il est bénéfique d'avoir plus de flux que des actionneurs réels /CPUs ou noyau ou que - alors ce qui est utilisé, je viens de les appeler CPUs ici/, - C'est si certains ruisseaux attendent vraiment des ressources autres que celles-ci CPUs.

Si les threads sont connectés CPU, Ensuite, le nombre parfait équivaut au nombre CPUs, Disponible à votre disposition. Si de nombreux threads s'attendent à entrer des fichiers ou d'accéder à la base de données, trafic réseau ou événements OS /etc/, Ensuite, quelques centaines peuvent être en ordre. Mais dans votre cas, il semble que ce ne soit pas.

Les flux de la piscine sont vraiment un moyen d'éviter la création continue et la destruction des flux dans des situations où il peut être relativement inefficace. Par exemple, si cela prend dix secondes pour démarrer le flux et que chacun d'entre eux n'effectue qu'un deuxième emploi, le pool de flux sera parfait.

Considérant que vous êtes susceptible de réduire le nombre de threads à quelque chose de plus petit que quatre cents /Dire, environ deux ou quatre/, Quoi, à son tour, augmentera la quantité de travail effectuée par chacun d'eux, le pool de threads peut ne pas être nécessaire. Mais encore une fois, cela dépend de la quantité de travail, qui sera complétée par des threads par rapport à leur coût de déclenchement.

Donc, tout était simple, je commencerais avec la version sans piscine et envisagé la possibilité de changer uniquement s'il y a un problème de productivité grave. Sinon, vous pouvez vous donner des travaux supplémentaires sans réels avantages.

Vous pouvez toujours partager votre travail sur quatre cents unités, mais la meilleure approche les mettrea simplement dans la file d'attente et faire chacun de vos fils tirez l'élément de la file d'attente lorsqu'il est prêt pour le traitement. Ainsi, le travail est automatiquement équilibré entre CPUs. Si pour une étrange raison CPU numéro 1 Cela fonctionne deux fois plus vite que d'autres, il recevra automatiquement deux fois plus de chargement de travail.

Il est plus important que vous ne le pensez simplement parce que presque certainement certainement CPUs va faire i.

Autres

choses - Ils sont peu susceptibles d'être entièrement dédiés à ce travail seulement.

Florian

Confirmation de:

Des centaines de flux sonnent comme un problème de tâches de calcul coûteuses. Très probablement, le programme passe plus de temps à changer de contexte que de traiter. Essayer d'utiliser N Flux /Où N - Nombre de noyaux dans votre voiture/ Et écraser le travail sur des blocs plus importants.

Clement

Confirmation de:

Premièrement, nombre maximum maximum
http://en.wikipedia.org/wiki/S ... ading
-c'est une perte de temps. 1 noyau avec hyperplow, ou SMT, ou comment veut-il appeler le producteur de chips, a 2 ou plus de flux simultanés. Vous devez savoir combien de flux simultanés peuvent gérer vos noyaux et la multiplier au nombre de cœurs. Pas besoin de faire plus de threads que cela. Tu avais 400 fils. À tout moment, probablement 396 D'entre eux dormaient.

Au lieu de vous inquiéter d'aligner les lignes de cache, vous devez vous inquiéter de

"locality"

. Lorsque vous faites défiler la taille de plus que le cache L2, Chaque accès mémoire est

Accès lent à la mémoire jusqu'à RAM

. Si vous faites pivoter les données inférieures au cache L2, Tout accès à la mémoire est dans

cache L2, lequel à ~100x plus rapide

. En outre, si tous les appels aux données seront lents, alors tous les flux d'exécution sur cpu sera arrêté. SMT Cela ne fonctionne que parce que le plus souvent un fil s'arrête en attente ram, alors CPU peut effectuer un autre flux. Si vous faites quelque chose de mal et que vous arrêtez tous les flux, vous éteigniez principalement SMT. Maintenant, vous n'avez pas de flux simultanés.

So...if Votre jeu de données est supérieur au cache L2, vous avez besoin

"strip mine"

. Étaler le calcul sur les pièces, suffisamment petit pour s'adapter au cache L2. Par exemple, si vous avez une matrice, divisez-le sur n x m carrés pouvant correspondre au cache L2, Et laissez le nombre correct de threads fonctionnent dessus. Lorsque cette bande est terminée, allez à la suivante et ainsi de suite. Si vous le faites correctement, votre code peut être dans 100 Une fois plus rapide.

Une autre façon d'augmenter la localité compresse vos données. Rendre les données le moins aussi peu que possible. Plus les données sont petites, plus elles restent dans le cache L2.

Giselle

Confirmation de:

Pour des travaux informatiques intensives, vous serez limité au nombre de cœurs que vous avez. Par conséquent, il est recommandé d'utiliser tant de flux que vous avez des noyaux.

Divisez les travaux sur le nombre de cœurs que vous avez, créez le même nombre de discussions et exécutez-la.

Si tous les éléments de travail sont indépendants, vous partagez simplement les mêmes groupes de taille. S'il y a une relation entre les éléments de travail /résultat item1 Avoir besoin item2/, Vous devez diviser quelque chose qui a du sens en fonction de cette dépendance.

David

Confirmation de:

Sur un ordinateur à processeur, vous travaillerez probablement plus lentement avec multithreading qu'avec un seul fileté,

si un

Tout ce que tu fais, - Ceci est un calcul dû à
http://en.wikipedia.org/wiki/Context_switch
.

Habituellement, si certains flux attendent des équipements périphériques, une approche multi-filetée peut offrir une certaine flexibilité à votre application.

Dans ton cas - CPU Tâches intensives, je doute qu'une approche multi-threads apporte la performance à votre demande.

Pour répondre aux questions, connectez-vous ou registre