Как очистить диапазон адресов в кеше процессора?

Я хочу проверить производительность программы пользовательского пространства в Linux, работающей на x86. Чтобы рассчитать производительность, мне необходимо сбросить в память определенные строки кеша (убедитесь, что эти строки недействительны, и при следующем запросе будет промах кеша).

Я уже видел предложения с использованием cacheflush(2), который должен быть системным вызовом, но g++ жалуется на то, что он не объявлен. Кроме того, я не могу использовать clflush_cache_range, который, по-видимому, может быть вызван только в программе ядра. Прямо сейчас я попытался использовать следующий код:

static inline void clflush(volatile void *__p)
{
    asm volatile("clflush %0" : "+m" (*(volatile char __force *)__p));
}

Но это дает следующую ошибку при компиляции:

ошибка: ожидаемое первичное выражение перед 'volatile'

Затем я изменил его следующим образом:

static inline void clflush(volatile void *__p)
{
    asm volatile("clflush %0" :: "m" (__p));
}

Он успешно скомпилирован, но результаты синхронизации не изменились. Я подозреваю, что компилятор удалил его с целью оптимизации. У кого-нибудь есть идеи, как я могу решить эту проблему?

C++ как правило работает на гораздо более высоком уровне, чем этот. Это не то, чем вы обычно должны заниматься в том, что касается языка.

Jesper Juhl 08.05.2019 20:17
g++ жалуется на то, что он не объявлен.#include <asm/cachectl.h>?
Swordfish 08.05.2019 20:26

Используйте _mm_clflush из emmintrin.h и имейте в виду, что создание флеша требует времени.

Filip Dimitrovski 08.05.2019 20:50

@Jesper, язык не заботится о производительности, но реальные реализации, и этот пользователь, так что я не уверен, что это имеет значение.

prl 08.05.2019 21:17

@JesperJuhl, спасибо. Я не беспокоюсь о языке. Я измеряю производительность некоторых вычислений на x86 по сравнению с ARM. В версии ARM данные не кэшируются, а в версии x86 кэшируются. Итак, мне нужно очистить эту строку кеша, чтобы иметь справедливое сравнение.

Hoda Aghaeikhouzani 08.05.2019 21:47

@Swordfish, Спасибо! когда я включаю этот заголовочный файл, я получаю следующую ошибку: фатальная ошибка: asm/cachectl.h: нет такого файла или каталога

Hoda Aghaeikhouzani 08.05.2019 21:49

то cachectl() недоступен для вашей платформы.

Swordfish 08.05.2019 21:52

@FilipDimitrovski, спасибо! Я попробовал _mm_clflush из x86intrin.h. Он скомпилирован правильно, но результаты синхронизации совпадают. Я начинаю подозревать, что предварительная выборка x86 неплохо справляется со своей задачей. Хотя я не могу этого доказать.

Hoda Aghaeikhouzani 08.05.2019 21:53

Невозможно ответить на этот вопрос, не показывая весь код.

Hadi Brais 09.05.2019 18:22

Нам также нужно знать процессор, на котором вы запускаете код, и точную команду, используемую для его компиляции.

Hadi Brais 09.05.2019 18:26
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
5
10
423
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Второй сбрасывает память, содержащую указатель __p, который находится в стеке, поэтому он не дает нужного вам эффекта.

Проблема с первым в том, что он использует макрос __force, который определен в ядре Linux и здесь не нужен. (Что делает __attribute__((force))?)

Если вы удалите __force, он будет делать то, что вы хотите.

(Вы также должны изменить его, чтобы не использовать имя переменной __p, которое является зарезервированным идентификатором.)

Если вы сбрасываете большое количество строк кеша, вы можете изменить его на использование clflushopt (если ваш процессор поддерживает это), а sfence следует за всеми сбросами.

prl 08.05.2019 21:28

Спасибо. Удалил __force и скомпилировал. Но результаты такие же. Как я упоминал выше, я начинаю подозревать, что предварительная выборка x86 делает довольно хорошую работу.

Hoda Aghaeikhouzani 08.05.2019 21:58

Это был бы еще лучший ответ, если бы вы указали, что вместо этого следует использовать _mm_clflush. И это asm volatile означает, что он определенно не оптимизирован.

Peter Cordes 09.05.2019 00:39

@HodaAgheikhouzani: предварительная выборка HW очень хорошо работает для последовательного доступа, но она не может справиться с касанием 1 int на строку кэша или что-то в этом роде с шагом 64 байта. Если ваш реальный код работает намного медленнее, например, несколько тактов на строку кэша, то да, он вполне может не отставать даже от DRAM.

Peter Cordes 09.05.2019 00:49

@PeterCordes, спасибо! Код представляет собой последовательный доступ к большому массиву, поэтому очистка кеша не повлияет на задержку.

Hoda Aghaeikhouzani 09.05.2019 18:29

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