Почему _mm_mfence() производит подсчет для перф события ALL_LOADS?

Я тестирую некоторые из внутренних операций поведения. Я удивился, когда заметил, что _mm_mfence() выдает инструкцию загрузки из пользовательского пространства, но она не учитывается в кэше данных L1 - попадание в буфер, пропуск или заполнение буфера. Я использую собственные события papi, такие как MEM_INST_RETIRED и MEM_LOAD_RETIRED для чтения счетчиков производительности. Этот кусок кода:

 for(int i=0; i < 1000000; i++){

    _mm_mfence();

  }

count ALL_LOADS: 737030, L1_HIT: 99, L1_MISS: 10, FB_HIT: 25. хотя без mfence накладные расходы на счетчики чтения выглядят примерно так: ALL_LOADS: 125, L1_HIT: 94, L1_MISS: 11, FB_HIT: 24

Я проверил и sfence и lfence не имеют этого влияния. Я использую -O3 для компиляции. Из скомпилированного файла, я думаю, он вызывает функцию __builtin_ia32_mfence, но я не смог найти много на нем.

В целом я понимаю, что делает _mm_mfence() и почему мы его используем, но теперь вопрос больше в том, как это работает. Было бы замечательно, если бы кто-нибудь мог объяснить или дать какую-либо связанную статью, чтобы понять это поведение.

1 ответ

Решение

_mm_mfence() компилируется только mfence инструкция, которая не является загрузкой или хранением, говоря архитектурно

Один или несколько мопов, которые он декодирует, могут микроархитектурно выполняться на порте загрузки и считаться нагрузкой.

Какой процессор вы используете? Если Skylake, я предполагаю, что вы обновили микрокод так mfence стоит больше, чем таблицы Агнера Фога, перечислите это как. (и он блокирует exec-порядка exec неопиций памяти, как lfence, См. Загружает ли и сохраняет ли единственные инструкции, которые переупорядочиваются? Очевидно, некоторые процессоры Intel до Skylake не делали этого для mfence.)

Другие вопросы по тегам