Barrières de mémoire efficaces

J’ai une application multithread, où chaque thread a une variable de type entier. Ces variables sont incrémentées lors de l’exécution du programme. À certains points du code, un thread compare sa variable de comptage à celles des autres threads.

Maintenant, puisque nous soaps que les threads s’exécutant sur plusieurs cœurs peuvent s’exécuter dans le désordre, un thread peut ne pas lire les valeurs de compteur attendues des autres threads. Pour résoudre ce problème, une solution consiste à utiliser une variable atomique, telle que std :: atomic de C ++ 11. Cependant, effectuer une clôture de mémoire à chaque incrément de compteurs ralentira considérablement le programme.

Maintenant, ce que je veux faire, c’est que lorsqu’un thread est sur le sharepoint lire le compteur d’un autre thread, une clôture de mémoire est alors créée et les compteurs de tous les threads sont mis à jour dans la mémoire à ce stade. Comment cela peut-il être fait en C ++? J’utilise Linux et g ++.

La bibliothèque standard C ++ 11 inclut la prise en charge des clôtures dans avec std::atomic_thread_fence .

Appeler cela appelle une clôture complète:

 std::atomic_thread_fence(std::memory_order_seq_cst); 

Si vous souhaitez émettre uniquement une clôture d’acquisition ou une libération, vous pouvez utiliser std:memory_order_acquire et std::memory_order_release .

Il existe des composants insortingnsèques x86 correspondant aux barrières de mémoire que vous pouvez utiliser vous-même. L’en-tête Windows a une macro de barrière de mémoire, vous devriez donc pouvoir trouver quelque chose d’équivalent pour Linux.

Ma suggestion serait d’avoir une fonction collectTimers () dans une classe de niveau supérieur pouvant demander à chaque thread son compteur (via queue / msg). De cette façon, les mises à jour des timers ne sont pas retardées, mais leur collecte est un peu plus lente.

Cela ne fonctionne que si vous avez une sorte de mécanisme de communication entre les threads.

Et pourquoi ne pas avoir un thread “contrôle”, à qui chaque thread rapporte ses incréments de compteur et demande les valeurs des autres?

Cela le rendrait très simple et efficace. Juste une suggestion.

Vous pouvez essayer quelque chose comme la conception du compteur de limite de vol dans la section 4.4.3 de http://mirror.nexcess.net/kernel.org/linux/kernel/people/paulmck/perfbook/perfbook.2011.08.28a.pdf.

Ce type de conception peut éliminer les opérations atomiques du raccourci (incrémenter le compteur par thread). Que la complexité en vaille la peine, c’est à vous de décider, bien sûr.

Vous pouvez utiliser boost :: asio :: strand dans ce but précis. Créez un gestionnaire responsable de la lecture du compteur. Ce gestionnaire peut être appelé à partir de plusieurs threads. Au lieu d’appeler directement le gestionnaire, placez-le dans un boost :: asio :: strand. Cela garantira que le gestionnaire ne peut pas être appelé simultanément par plusieurs threads.

http://www.boost.org/doc/libs/1_35_0/doc/html/boost_asio/tutorial/tuttimer5.html

J’espère avoir bien compris la question.