Почему _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
.)