Подтвердить что ты не робот

Как CLFLUSH работает для адреса, который еще не находится в кеше?

Мы пытаемся использовать инструкцию Intel CLFLUSH для очистки содержимого кеша процесса в Linux в пользовательском пространстве.

Мы создаем очень простую C-программу, которая сначала обращается к большому массиву, а затем вызывает CLFLUSH, чтобы очистить виртуальное адресное пространство всего массива. Мы измеряем задержку, необходимую CLFLUSH для очистки всего массива. Размер массива в программе - это вход, и мы меняем вход от 1 МБ до 40 МБ с шагом 2 МБ.

В нашем понимании CLFLUSH должен очистить содержимое в кеше. Таким образом, мы ожидаем, что латентность промывки всего массива сначала будет линейно возрастать с точки зрения размера массива, а затем латентность должна перестать увеличиваться после того, как размер массива будет больше 20 МБ, что является величиной LLC нашей программы,

Однако результат эксперимента весьма удивителен, как показано на рисунке. Задержка не перестает увеличиваться после того, как размер массива превышает 20 МБ.

Нам интересно, может ли CLFLUSH потенциально ввести адрес до того, как CLFLUSH сбросит адрес из кеша, если адрес еще не находится в кеше? Мы также попытались выполнить поиск в руководстве разработчика программного обеспечения Intel и не нашли никакого объяснения того, что CLFLUSH сделает, если адрес не находится в кеше.

введите описание изображения здесь

Ниже приведены данные, которые мы использовали для рисования фигуры. Первый столбец - это размер массива в КБ, а второй столбец - это латентность очистки всего массива за считанные секунды.

Любое предложение/совет более чем оценено.

[Модифицированный]

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

SCENARIO=Read Only
1024,.00158601000000000000
3072,.00299244000000000000
5120,.00464945000000000000
7168,.00630479000000000000
9216,.00796194000000000000
11264,.00961576000000000000
13312,.01126760000000000000
15360,.01300500000000000000
17408,.01480760000000000000
19456,.01696180000000000000
21504,.01968410000000000000
23552,.02300760000000000000
25600,.02634970000000000000
27648,.02990350000000000000
29696,.03403090000000000000
31744,.03749210000000000000
33792,.04092470000000000000
35840,.04438390000000000000
37888,.04780050000000000000
39936,.05163220000000000000

SCENARIO=Read and Write
1024,.00200558000000000000
3072,.00488687000000000000
5120,.00775943000000000000
7168,.01064760000000000000
9216,.01352920000000000000
11264,.01641430000000000000
13312,.01929260000000000000
15360,.02217750000000000000
17408,.02516330000000000000
19456,.02837180000000000000
21504,.03183180000000000000
23552,.03509240000000000000
25600,.03845220000000000000
27648,.04178440000000000000
29696,.04519920000000000000
31744,.04858340000000000000
33792,.05197220000000000000
35840,.05526950000000000000
37888,.05865630000000000000
39936,.06202170000000000000
4b9b3361

Ответ 1

Вы хотите посмотреть новое руководство по оптимизации для Skylake, Intel выпустила еще одну версию clflush, называемую clflush_opt, которая слабо упорядочена и будет работать намного лучше в вашем сценарии.

См. раздел 7.5.7 здесь - http://www.intel.com/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-optimization-manual.pdf

В общем случае пропускная способность CLFLUSHOPT выше, чем у CLFLUSH, потому что CLFLUSHOPT заказывает себя в отношении меньшего набора как описано выше и в разделе 7.5.6. пропускная способность CLFLUSHOPT также будет меняться. При использовании CLFLUSHOPT, потоки модифицированных строк кэша будут иметь более высокую стоимость, чем стирание строк кеша в немодифицированных состояниях. CLFLUSHOPT предоставит преимущество в производительности над CLFLUSH для строк кэша в любых когерентных состояния. CLFLUSHOPT более подходит для промывки больших буферов (например, больше, чем много килобайт), comp ared для CLFLUSH. В однопоточном приложения, промывные буферы с использованием CLFLUSHOPT могут быть до 9X лучше, чем использование CLFLUSH с микроархитектурой Skylake.

В этом разделе также объясняется, что сбрасывание измененных данных происходит медленнее, что, очевидно, происходит от штрафа обратной записи.

Что касается увеличения задержки, измеряете ли вы общее время, чтобы пройти по диапазону адресов и clflush каждой линии? В этом случае вы линейно зависимы от размера массива, даже когда он передает размер LLC. Даже если линий там нет, clflush придется обрабатывать движком выполнения и блоком памяти и искать всю иерархию кэша для каждой строки, даже если она не присутствует.

Ответ 2

Это не объясняет колено в графе только для чтения, но объясняет, почему он не плато.


Я не стал тестировать локально, чтобы изучить разницу между случаем горячего и холодного кеша, но я встретил номер производительности для clflush:

Этот репозиторий с проверкой времени ожидания/пропускной способности инструкции AIDA64 содержит однострочный Процессор Haswell-E (i7-5820K) с пропускной способностью clflush на один из 99,08 циклов. Он не говорит, повторяется ли это для одного и того же адреса или что.

Итак, clflush не находится где угодно, даже если ему не нужно выполнять какую-либо работу. Он по-прежнему является микрокодированной инструкцией, не сильно оптимизированной, потому что обычно это не большая часть рабочей нагрузки ЦП.

Skylake готовится к этому для изменения, с поддержкой постоянной памяти, подключенной к контроллеру памяти: On Skylake (i5-6400T), измеренная пропускная способность:

  • clflush: один за ~ 66.42 цикла
  • clflushopt: один за ~ 56.33 цикла

Возможно, clflushopt больше выигрывает, когда некоторые из строк являются фактически грязным кешем, который нуждается в очистке, возможно, когда L3 занят другими ядрами, делающими то же самое. Или, может быть, они просто хотят получить программное обеспечение с использованием слабо упорядоченной версии ASAP, прежде чем сделать еще большие улучшения пропускной способности. Это ~ 15% быстрее в этом случае, что неплохо.