почему производительность memory_order_relaxed такая же, как и memory_order_seq_cst - PullRequest
0 голосов
/ 16 декабря 2018

Я создал простой тест, чтобы проверить, насколько std::memory_order_relaxed быстрее, чем std::memory_order_seq_cst значение для приращения atomic<int>.Однако производительность в обоих случаях была одинаковой.
Мой компилятор: gcc версии 7.3.0 (Ubuntu 7.3.0-27ubuntu1 ~ 18.04)
Аргументы сборки: g ++ -m64 -O3 main.cpp -std = c ++17-lpthread
Процессор: Intel® Core ™, процессор i7-2670QM @ 2,20 ГГц, 4 ядра, 2 потока на ядро ​​
Тестовый код:

#include <vector>
#include <iostream>
#include <thread>
#include <atomic>
#include <chrono>
#include <functional>

std::atomic<int> cnt = {0};

void run_test_order_relaxed()
{
    std::vector<std::thread> v;
    for (int n = 0; n < 4; ++n) {
        v.emplace_back([]() {
            for (int n = 0; n < 30000000; ++n) {
                cnt.fetch_add(1, std::memory_order_relaxed);
            }
        });
    }
    std::cout << "rel: " << cnt.load(std::memory_order_relaxed);
    for (auto& t : v)
        t.join();
    }

void run_test_order_cst()
{
    std::vector<std::thread> v;
    for (int n = 0; n < 4; ++n) {
        v.emplace_back([]() {
            for (int n = 0; n < 30000000; ++n) {
                cnt.fetch_add(1, std::memory_order_seq_cst);
            }
        });
    }
    std::cout << "cst: " << cnt.load(std::memory_order_seq_cst);
    for (auto& t : v)
        t.join();
}

void measure_duration(const std::function<void()>& func)
{
    using namespace std::chrono;
    high_resolution_clock::time_point t1 = high_resolution_clock::now();
    func();
    high_resolution_clock::time_point t2 = high_resolution_clock::now();
    auto duration = duration_cast<milliseconds>( t2 - t1 ).count();
    std::cout << " duration: " << duration << "ms" << std::endl;
}

int main()
{
    measure_duration(&run_test_order_relaxed);
    measure_duration(&run_test_order_cst); 
    return 0;
}

Почему std::memory_order_relaxed и std::memory_order_seq_cst всегда дают почти одинаковые результаты?
Результат:
rel: 2411 длительность: 4440 мс
cst: 120000164 длительность: 4443 мс

1 Ответ

0 голосов
/ 16 декабря 2018

Независимо от настройки порядка памяти, вам требуется атомарная операция в обоих циклах.Оказывается, что с процессорами x86, которые по своей природе строго упорядочены в большинстве ситуаций, это приводит к использованию одних и тех же кодов asm для каждого fetch_add: lock xadd.Эта атомарная операция на процессорах x86 всегда последовательна, поэтому здесь нет возможности оптимизации при указании расслабленного порядка памяти.

Использование расслабленного порядка памяти позволяет дополнительно оптимизировать окружающие операции, но ваш код больше не обеспечиваетВозможности оптимизации, поэтому выдаваемый код одинаков.Обратите внимание, что результаты могут отличаться при использовании слабо упорядоченного процессора (например, ARM) или при большем количестве манипуляций с данными в цикле (что может предложить больше возможностей переупорядочения).

С cppreference (мой курсив):

std :: memory_order указывает, как регулярные неатомарные обращения к памяти должны быть упорядочены вокруг атомарной операции.

Документ Модели памяти для программистов на C / C ++ предоставляет много более подробных сведений об этом.

В качестве примечания, многократно работающийатомарные эталонные тесты или запуск их на разных процессорах x86 (даже одного и того же производителя) может привести к совершенно разным результатам, поскольку потоки могут не распределяться по всем ядрам в равной степени, а на задержки кэша влияет то, является ли это локальным ядром, другоеядро на том же чипе или на другом чипе.Это также зависит от того, как конкретный процессор обрабатывает потенциальные конфликты согласованности.Кроме того, кэши уровня 1, 2 и 3 ведут себя по-разному, как и оперативная память, поэтому общий размер набора данных также оказывает существенное влияние.См. Оценка стоимости атомарных операций на современных архитектурах .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...