J'utilise bool volatile depuis des années pour le contrôle de l'exécution des threads et cela a bien fonctionné
// in my class declaration
volatile bool stop_;
-----------------
// In the thread function
while (!stop_)
{
do_things();
}
Maintenant, comme c ++ 11 a ajouté la prise en charge des opérations atomiques, j'ai décidé d'essayer cela à la place
// in my class declaration
std::atomic<bool> stop_;
-----------------
// In the thread function
while (!stop_)
{
do_things();
}
Mais c'est plusieurs ordres de grandeur plus lent que le volatile bool
!
Le scénario de test simple que j'ai écrit prend environ 1 seconde pour terminer avec volatile bool
approche. Avec std::atomic<bool>
cependant j'attends depuis environ 10 minutes et j'ai abandonné!
J'ai essayé d'utiliser memory_order_relaxed
drapeau avec load
et store
au même effet.
Ma plate-forme: Windows 7 64 bits MinGW gcc 4.6.x
Qu'est-ce que je fais mal?
UPD
Oui, je sais que volatile ne rend pas un thread variable sûr. Ma question n'est pas volatile, c'est pourquoi l'atomique est ridiculement lent.
PD2 @all, merci pour vos commentaires - je vais essayer toutes les suggestions quand j'arriverai à ma machine ce soir.
Code de "Olaf Dietsche"
USE ATOMIC
real 0m1.958s
user 0m1.957s
sys 0m0.000s
USE VOLATILE
real 0m1.966s
user 0m1.953s
sys 0m0.010s
SI VOUS UTILISEZ GCC SMALLER 4.7
http://gcc.gnu.org/gcc-4.7/changes.html
La prise en charge des opérations atomiques spécifiant le modèle de mémoire C++ 11/C11 a été ajoutée. Ces nouvelles routines __atomic remplacent les routines intégrées __sync existantes.
La prise en charge atomique est également disponible pour les blocs de mémoire. Des instructions sans verrouillage seront utilisées si un bloc de mémoire a la même taille et le même alignement qu'un type d'entier pris en charge. Les opérations atomiques qui ne prennent pas en charge le verrouillage sont laissées en tant qu'appels de fonction. Un ensemble de fonctions de bibliothèque est disponible sur le wiki atomique de GCC dans la section "External Atomics Library".
Alors oui ... la seule solution est de passer à GCC 4.7
Comme je suis curieux à ce sujet, je l'ai testé moi-même sur Ubuntu 12.04, AMD 2,3 GHz, gcc 4.6.3.
#if 1
#include <atomic>
std::atomic<bool> stop_(false);
#else
volatile bool stop_ = false;
#endif
int main(int argc, char **argv)
{
long n = 1000000000;
while (!stop_) {
if (--n < 0)
stop_ = true;
}
return 0;
}
Compilé avec g++ -g -std=c++0x -O3 a.cpp
Bien, même conclusion que @aleguna:
juste bool
:
réel 0m0.004s
utilisateur 0m0.000s
sys 0m0.004s
volatile bool
:
$ time ./a.out
réel 0m1.413s
utilisateur 0m1.368s
sys 0m0.008s
std::atomic<bool>
:
$ time ./a.out
réel 0m32.550s
utilisateur 0m32.466s
sys 0m0.008s
std::atomic<int>
:
$ time ./a.out
réel 0m32.091s
utilisateur 0m31.958s
sys 0m0.012s
Je suppose que c'est une question de matériel. Lorsque vous écrivez volatile, vous dites au compilateur de ne rien supposer de la variable, mais si je comprends bien, le matériel la traitera toujours comme une variable normale. Cela signifie que la variable sera dans le cache tout le temps. Lorsque vous utilisez atomic, vous utilisez des instructions matérielles spéciales, ce qui signifie probablement que la variable est extraite de la mémoire principale chaque fois qu'elle est utilisée. La différence de timing est cohérente avec cette explication.