Pourquoi est std::mutex plus vite que std::atomique?

Je veux mettre des objets dans std::vector en mode multithread. J'ai donc décidé de comparer les deux approches: l'une utilise des std::atomic et les autres std::mutex. Je vois que la seconde approche est plus rapide que le premier. Pourquoi?

J'utilise GCC 4.8.1 et, sur ma machine (8 threads), je vois que la première solution nécessite 391502 microsecondes et la deuxième solution nécessite 175689 microsecondes.

#include <vector>
#include <omp.h>
#include <atomic>
#include <mutex>
#include <iostream>
#include <chrono>

int main(int argc, char* argv[]) {
    const size_t size = 1000000;
    std::vector<int> first_result(size);
    std::vector<int> second_result(size);
    std::atomic<bool> sync(false);

    {
        auto start_time = std::chrono::high_resolution_clock::now();
        #pragma omp parallel for schedule(static, 1)
        for (int counter = 0; counter < size; counter++) {
            while(sync.exchange(true)) {
                std::this_thread::yield();
            };
            first_result[counter] = counter;
            sync.store(false) ;
        }
        auto end_time = std::chrono::high_resolution_clock::now();
        std::cout << std::chrono::duration_cast<std::chrono::microseconds>(end_time - start_time).count() << std::endl;
    }

    {
        auto start_time = std::chrono::high_resolution_clock::now();
        std::mutex mutex; 
        #pragma omp parallel for schedule(static, 1)
        for (int counter = 0; counter < size; counter++) {
            std::unique_lock<std::mutex> lock(mutex);       
            second_result[counter] = counter;
        }
        auto end_time = std::chrono::high_resolution_clock::now();
        std::cout << std::chrono::duration_cast<std::chrono::microseconds>(end_time - start_time).count() << std::endl;
    }

    return 0;
}
1. Postez votre compilateur, les options de compilation & la mesure des résultats, s'il vous plaît. 2. Faire quelque chose d'observable avec les données obtenues après la mesure, sinon un "suffisamment bonne" de l'optimiseur peut supprimer le code comme mort.
En 32 bits et la version validée avec Visual Studio 2013-je obtenir 0, 46800 et 64 bits me donne 0, 62400 constante, de sorte qu'il semble atomique est soit super rapide, ou le harnais de test n'est pas vraiment de travail. Vous devez également savoir, dans le cas où vous l'utilisez, que dans Visual Studio 2013 et au-dessous de high_resolution_clock n'est pas différents que les system_clock. stackoverflow.com/q/16299029/920069
Ce code est gravement mis à mal, peu importe. Les opérations atomiques avec memory_order_relaxed ne sont pas les opérations de synchronisation.
J'ai mis à jour mon code. Maintenant quand j'utilise quatre fils la première solution est plus rapide que la seconde (25-30%). Mais la première solution est plus lent que la seconde si je augmenter le nombre de threads (20-25%).
Qui s'en soucie. Le code est toujours en panne. Quelles conclusions avez-vous pense que vous pouvez en tirer? De code cassé est le plus rapide? De code cassé est plus lent? Comment est l'un de ceux-elle utile?

OriginalL'auteur Sergey Malashenko | 2015-04-09