что на самом деле измеряет тест пропускной способности памяти STREAM?

У меня есть несколько вопросов по STREAM (http://www.cs.virginia.edu/stream/ref.html#runrules).

  1. Ниже комментарий от stream.c. Каково обоснование требования, чтобы массивы были в 4 раза больше размера кеша?
 *       (a) Each array must be at least 4 times the size of the
 *           available cache memory. I don't worry about the difference
 *           between 10^6 and 2^20, so in practice the minimum array size
 *           is about 3.8 times the cache size.
  1. Первоначально я предполагал, что STREAM измеряет пиковую пропускную способность памяти. Но позже я обнаружил, что, добавляя дополнительные массивы и доступ к массивам, я могу получить более высокие значения пропускной способности. Так что мне кажется, что STREAM не гарантирует насыщения пропускной способности памяти. Тогда мой вопрос: что на самом деле измеряет STREAM и как вы используете цифры, сообщаемые STREAM?

Например, я добавил два дополнительных массива и обратился к ним вместе с исходными массивами a/b/c. Я изменяю учет байтов соответственно. Благодаря этим двум дополнительным массивам пропускная способность увеличилась примерно на 11,5%.

> diff stream.c modified_stream.c
181c181,183
<                       c[STREAM_ARRAY_SIZE+OFFSET];
---
>                       c[STREAM_ARRAY_SIZE+OFFSET],
>                       e[STREAM_ARRAY_SIZE+OFFSET],
>                       d[STREAM_ARRAY_SIZE+OFFSET];
192,193c194,195
<     3 * sizeof(STREAM_TYPE) * STREAM_ARRAY_SIZE,
<     3 * sizeof(STREAM_TYPE) * STREAM_ARRAY_SIZE
---
>     5 * sizeof(STREAM_TYPE) * STREAM_ARRAY_SIZE,
>     5 * sizeof(STREAM_TYPE) * STREAM_ARRAY_SIZE
270a273,274
>             d[j] = 3.0;
>             e[j] = 3.0;
335c339
<           c[j] = a[j]+b[j];
---
>           c[j] = a[j]+b[j]+d[j]+e[j];
345c349
<           a[j] = b[j]+scalar*c[j];
---
>           a[j] = b[j]+scalar*c[j] + d[j]+e[j];

CFLAGS = -O2 -fopenmp -D_OPENMP -DSTREAM_ARRAY_SIZE=50000000

Мой кеш последнего уровня составляет около 35 МБ.

Любой комментарий?

Спасибо!

Это для сервера Skylake Linux.


person yeeha    schedule 11.05.2019    source источник
comment
Кроме того, я пробовал разные конфигурации numactl, чтобы потоки или память были закреплены на разных узлах numa. Мой измененный stream.c всегда сообщает о пропускной способности более 10% во всех конфигурациях. Поэтому я думаю, что мы можем исключить возможность того, что NUMA-ность вызывает дисперсию.   -  person yeeha    schedule 11.05.2019
comment
Один поток обычно не может насытить пропускную способность DRAM, особенно на серверном чипе Intel. Пропускная способность одноядерного процессора ограничена задержкой/max_concurrency количества невыполненных запросов вне ядра, которые он может иметь в процессе выполнения, а не пропускной способностью контроллера DRAM. Почему Skylake намного лучше, чем Broadwell-E по пропускной способности однопоточной памяти? сравнивает Broadwell-E и четырехъядерный рабочий стол Skylake. .   -  person Peter Cordes    schedule 11.05.2019
comment
О, но вы используете OpenMP, так что, я думаю, вы измеряете совокупную пропускную способность с насыщением всех ядер? Ваше изменение выглядит так, будто оно больше смещает баланс в сторону чтения. IDK, если вы получаете какие-либо попадания в кэш L3. Предположительно, никакие данные не распределяются между потоками, тогда вы ожидаете, что больше чтений поможет больше.   -  person Peter Cordes    schedule 11.05.2019
comment
Да, я измеряю совокупную пропускную способность. Теперь я запутался, что на самом деле говорит STREAM, если он не насыщает пропускную способность. Какие еще тесты можно порекомендовать? Спасибо   -  person yeeha    schedule 11.05.2019
comment
STREAM сообщает вам, насколько быстро может работать такой цикл. Когда все ядра активны, пропускная способность DRAM обычно должна быть близка к насыщению, но попадание в кэш может привести к завышению общего значения. Современные процессоры — чрезвычайно сложные звери, и при прогнозировании производительности одного цикла по производительности другого существует множество подводных камней. Сравните свое собственное приложение или ключевой цикл из него, если вам это небезразлично. Но для характеристики оборудования STREAM является одним из используемых тестов, в то время как другие включают SiSoft Sandra.   -  person Peter Cordes    schedule 11.05.2019
comment
например если вы погуглите современные обзоры оборудования, они часто запускают тесты пропускной способности памяти Sandra и/или AIDA64. pcworld. com/article/3298859/ или kitguru.net/components/motherboard/ryan-martin/. Я думаю, что эти тесты написаны вручную на ассемблере, чтобы, возможно, попытаться приблизиться к насыщению пропускной способности при чтении, записи или копировании. Пропускная способность STREAM TRIAD (или ваша с большим количеством входных потоков) менее чисто синтетическая, особенно. когда вы сами его компилируете.   -  person Peter Cordes    schedule 11.05.2019
comment
Я думаю, вы забываете, что записи (если только не используются невременные/объединяющие записи оптимизации) включают в себя неявное чтение. Добавляя два чтения, вы увеличиваете кажущуюся пропускную способность примерно на 11% (3 кажущихся доступа с четырьмя фактическими обращениями против 5 кажущихся обращений с шестью фактическими обращениями; (5/6)/(3/4) = (10/9)≈1,11). Кажется, это объясняет большую часть различий.   -  person Paul A. Clayton    schedule 11.05.2019


Ответы (3)


Доступ к памяти в современных компьютерах намного сложнее, чем можно было бы ожидать, и очень трудно сказать, когда «высокоуровневая» модель разваливается из-за некоторых «низкоуровневых» деталей, о которых вы раньше не знали. ..

Тестовый код STREAM измеряет только время выполнения — все остальное является производным. Полученные цифры основаны как на решениях о том, что я считаю «разумным», так и на предположениях о том, как работает большинство компьютеров. Правила выполнения являются продуктом проб и ошибок — попыткой сбалансировать переносимость с универсальностью.

Бенчмарк STREAM сообщает значения «пропускной способности» для каждого из ядер. Это простые вычисления, основанные на предположении, что каждый элемент массива в правой части каждого цикла должен быть прочитан из памяти, а каждый элемент массива в левой части каждого цикла должен быть записан в память. Тогда «пропускная способность» — это просто общий объем перемещенных данных, разделенный на время выполнения.

В этом простом вычислении задействовано удивительное количество допущений.

  • Модель предполагает, что компилятор генерирует код для выполнения всех операций загрузки, сохранения и арифметических операций, которые подразумеваются подсчетами трафика памяти. Подход, используемый в STREAM для поощрения этого, довольно надежен, но продвинутый компилятор может заметить, что все элементы массива в каждом массиве содержат одно и то же значение, поэтому на самом деле необходимо обрабатывать только один элемент из каждого массива. (Вот как работает код проверки.)
  • Иногда компиляторы перемещают вызовы таймера из их местоположений в исходном коде. Это (тонкое) нарушение языковых стандартов, но его легко обнаружить, поскольку обычно оно приводит к бессмысленным результатам.
  • Модель предполагает незначительное количество попаданий в кэш. (При попадании в кеш вычисляемое значение по-прежнему является «пропускной способностью», а не «пропускной способностью памяти».) Ядра STREAM Copy и Scale загружают только один массив (и сохраняют один массив), поэтому, если хранилища обходят кеш , общий объем трафика, проходящего через кеш на каждой итерации, равен размеру одного массива. Адресация и индексирование кэша иногда очень сложны, а политики замены кэша могут быть динамическими (либо псевдослучайными, либо основанными на показателях использования во время выполнения). В качестве компромисса между размером и точностью я выбрал 4x в качестве минимального размера массива по отношению к размеру кэша, чтобы гарантировать, что большинство систем имеют очень низкую долю попаданий в кэш (т. е. достаточно низкую, чтобы иметь незначительное влияние). по заявленной производительности).
  • Счетчики трафика данных в STREAM не «отдают должное» дополнительным передачам, которые выполняет аппаратное обеспечение, но которые не были запрошены явно. В первую очередь это относится к трафику "выделения записи" - большинство систем читают каждый сохраняемый целевой адрес из памяти до того, как хранилище сможет обновить соответствующую строку кэша. Во многих системах есть возможность пропустить это «выделение записи», либо путем выделения строки в кеше без ее чтения (POWER), либо путем выполнения операций сохранения, которые обходят кеш и идут прямо в память (x86). Дополнительные примечания по этому поводу находятся по адресу http://sites.utexas.edu/jdm4372/2018/01/01/notes-on-non-temporal-aka-streaming-stores/
  • Многоядерные процессоры с более чем двумя каналами DRAM обычно не могут достичь асимптотической пропускной способности, используя только одно ядро. Директивы OpenMP, изначально предназначенные для больших систем с общей памятью, теперь должны быть включены почти на каждом процессоре с более чем двумя каналами DRAM, если вы хотите достичь асимптотических уровней пропускной способности.
  • Пропускная способность одного ядра по-прежнему важна, но обычно она ограничивается количеством промахов кэша, которые может генерировать одно ядро, а не пиковой пропускной способностью DRAM системы. Проблемы представлены в http://sites.utexas.edu/jdm4372/2016/11/22/sc16-invited-talk-memory-bandwidth-and-system-balance-in-hpc-systems/
  • В случае с одним ядром количество невыполненных кэш-памятей данных L1 слишком мало, чтобы получить полную пропускную способность — для вашего масштабируемого процессора Xeon требуется около 140 одновременных кэш-промахов для каждого сокета, но одно ядро ​​может поддерживать только 10-12. Кэш данных L1 отсутствует. Аппаратные предварительные выборки L2 могут генерировать дополнительный параллелизм памяти (до ~ 24 промахов кеша на ядро, если я правильно помню), но для достижения средних значений около верхней границы этого диапазона требуется одновременный доступ к большему количеству страниц по 4 КБ. Ваши дополнительные операции чтения массива дают аппаратным средствам предварительной выборки L2 больше возможностей генерировать (близкое к) максимальное количество одновременных обращений к памяти. Увеличение на 11%-12% вполне разумно.
  • Также ожидается, что увеличение доли операций чтения повысит производительность при использовании всех ядер. В этом случае преимущество заключается, прежде всего, в уменьшении количества «приостановок чтения-записи» на интерфейсе DDR4 DRAM. При полном отсутствии хранилищ устойчивая пропускная способность должна достигать 90 % пикового значения на этом процессоре (при использовании 16 или более ядер на сокет).

Дополнительные примечания по избеганию трафика «запись-распределение»:

  1. В архитектурах x86 хранилища с обходом кеша обычно делают недействительным соответствующий адрес из локальных кешей и удерживают данные в «буфере объединения записи» до тех пор, пока процессор не решит поместить данные в память. Другим процессорам разрешается хранить и использовать «устаревшие» копии строки кэша в течение этого периода. Когда буфер объединения записей сбрасывается, строка кэша отправляется в контроллер памяти в транзакции, которая очень похожа на запись DMA IO. Контроллер памяти несет ответственность за выдачу «глобальных» недействительных адресов перед обновлением памяти. Следует соблюдать осторожность, когда эти потоковые хранилища используются для обновления памяти, которая используется совместно ядрами. Общая модель заключается в выполнении потоковых хранилищ, выполнении ограждения хранилища, а затем выполнении «обычного» сохранения в переменной «флаг». Ограждение хранилища гарантирует, что ни один другой процессор не сможет увидеть обновленную переменную «флаг», пока результаты всех потоковых хранилищ не станут видны глобально. (При использовании последовательности «обычных» хранилищ результаты всегда становятся видимыми в порядке программы, поэтому ограждение хранилища не требуется.)
  2. В архитектуре PowerPC/POWER можно использовать команду DCBZ (или DCLZ), чтобы избежать распределения трафика записи. Если строка находится в кеше, ее содержимое обнуляется. Если строки нет в кеше, в кеше выделяется строка с нулевым содержимым. Недостатком этого подхода является то, что здесь отображается размер строки кэша. DCBZ на PowerPC с 32-байтными строками кэша очистит 32 байта. Та же инструкция на процессоре со 128-байтными строками кэша очистит 128 байт. Это раздражало продавца, который использовал оба. Я не помню достаточно деталей модели упорядочения памяти POWER, чтобы комментировать, как/когда транзакции когерентности становятся видимыми с помощью этой инструкции.
person John D McCalpin    schedule 12.05.2019
comment
Круто, я не знал, что ты на Stack Overflow. Попробуйте изменить свое имя пользователя, чтобы люди знали, что это вы. :) И, кстати, даже некоторые двухканальные процессоры для настольных ПК/ноутбуков не полностью насыщают пропускную способность памяти одним ядром, например, при запуске glibc memcpy или memset. Они намного ближе, чем одно ядро ​​​​на большом Xeon, в зависимости от соотношения тактовой частоты ядра и тактовой частоты памяти, но особенно с быстрой DDR4, я думаю, что Skylake может стать узким местом из-за ограниченного параллелизма памяти. буферы заполнения строки и/или буферы суперочереди L2. - person Peter Cordes; 13.05.2019
comment
В дополнение к вашему выступлению на Stack Overflow обсуждалось: Почему Skylake намного лучше, чем Broadwell-E, для пропускной способности однопоточной памяти? и раздел Платформы с привязкой к задержке в ответе Трэвиса Даунса (@BeeOnRope's) на Расширенный REP MOVSB ​​для memcpy - person Peter Cordes; 13.05.2019
comment
Многие системы имеют возможность пропустить это выделение для записи, либо выделив строку в кеше, не читая ее. Есть ли документ об этой функции? Если чтение памяти пропускается, как процессор гарантирует, что неизмененные данные в той же строке кэша останутся нетронутыми? Спасибо - person yeeha; 13.05.2019
comment
@yeeha: см. мой ответ: на x86 это делается с хранилищами NT, которые не связаны. Они могут пропустить шаг чтения/изменения/записи только в том случае, если вы выполняете полную запись строки; вот почему они также называются потоковыми магазинами, потому что это их вариант использования. См. Enhanced REP MOVSB ​​для memcpy, на который я уже ссылался, чтобы узнать больше об этой функции. (Этот ответ имеет дополнительные ссылки.) - person Peter Cordes; 15.05.2019
comment
@Peter Cordes - незначительная гнида: на x86 невременные хранилища согласованы в большинстве (но, возможно, не во всех) аспектах. Невременные хранилища следуют другой модели упорядочения — они могут стать видимыми позже, чем ожидалось. Их иногда называют слабоупорядоченными магазинами или неглобально упорядоченными магазинами. Единственный аспект, который можно было бы назвать несогласованным, заключается в том, что (как и при записи IO DMA) при сбросе буфера объединения записей во все кэши отправляется команда аннулирования. Это сделает недействительными даже грязные строки, не вызывая обратной записи грязных данных. - person John D McCalpin; 19.05.2019
comment
@JohnDMcCalpin: О, отлично, я не знал, что магазины NT могут избежать обратной записи строк, которые они делают недействительными, другими ядрами. Я согласен, что непоследовательность точно не описывает их. Я так думал, потому что данные находятся в LFB, где ничто не может их отследить (кроме текущего ядра, если вы перезагрузите), но обычные хранилища также находятся в буфере хранилища, прежде чем они будут зафиксированы в измененной строке в L1d. Intel предупреждает об использовании NT-хранилищ в строках, содержащих блокировку или другую цель атомарного RMW, но я точно не знаю, почему (их формулировка звучала как правильность, а не просто производительность). - person Peter Cordes; 19.05.2019
comment
@PeterCordes При дальнейшем изучении внутренностей протокола согласованности Intel я обнаружил некоторые доказательства того, что процессоры SKX/CLX будут записывать обратно M строк состояния, прежде чем они будут перезаписаны операциями записи DMA (или потоковыми хранилищами), но я не пытался проверить это еще. От WB может потребоваться правильное обновление тегов кеша/отслеживающих фильтров/каталогов памяти/и т. д. На практике это должно быть редко, так что это не проблема производительности. Бесшумная перезапись строк M-состояния при записи DMA была особенностью процессоров по крайней мере одного из процессоров, над которыми я работал.... ;-) - person John D McCalpin; 17.08.2020

Ключевым моментом здесь, как указано в ответе доктора Бэндвида, является то, что STREAMS подсчитывает только полезную пропускную способность, видимую исходным кодом. (Он автор теста.)

На практике поток записи также будет нести расходы на полосу пропускания при чтении для запросов RFO (Read For Ownership). Когда ЦП хочет записать 16 байт (например) в строку кэша, сначала он должен загрузить исходную строку кэша, а затем изменить ее в кэше L1d.

(Если ваш компилятор автоматически не векторизируется с помощью NT-хранилищ, которые обходят кеш и избегают этого RFO. Некоторые компиляторы будут делать это для циклов, которые, как они ожидают, запишут массив, слишком большой для кеша, прежде чем какой-либо из него будет перечитан. .)

Подробнее о хранилищах с обходом кеша, которые избежать РФО.


Поэтому увеличение количества потоков чтения по сравнению с потоками записи приблизит наблюдаемую программным обеспечением пропускную способность к фактической аппаратной пропускной способности. (Кроме того, смешанная рабочая нагрузка чтения/записи для памяти может быть не совсем эффективной.)

person Peter Cordes    schedule 12.05.2019
comment
Я должен был сделать свой комментарий ответом, вздох . - person Paul A. Clayton; 13.05.2019

Целью теста STREAM является не измерение пиковой пропускной способности памяти (т. е. максимальная пропускная способность памяти, которая может быть достигнута в системе), а измерение «пропускной способности памяти» ряда ядер (КОПИРОВАНИЕ, МАСШТАБ, СУММ, и TRIAD), которые важны для сообщества HPC. Таким образом, когда пропускная способность, сообщаемая STREAM, выше, это означает, что приложения HPC, вероятно, будут работать быстрее в системе.

Также важно понимать значение термина «пропускная способность памяти» в контексте теста STREAM, который объясняется в последнем разделе документации. Как упоминалось в этом разделе, существует по крайней мере три способа подсчета количества байтов для теста. Тест STREAM использует метод STREAM, который подсчитывает количество прочитанных и записанных байтов на уровне исходного кода. Например, в ядре SUM (a(i) = b(i) + c(i)) два элемента читаются, а один записывается. Следовательно, если предположить, что все обращения осуществляются к памяти, количество байтов, доступ к которым осуществляется из памяти за одну итерацию, равно количеству массивов, умноженному на размер элемента (который равен 8 байтам). STREAM вычисляет пропускную способность путем умножения общего количества элементов, к которым осуществляется доступ (подсчитанных с помощью метода STREAM), на размер элемента и деления на время выполнения ядра. Чтобы учесть изменения от запуска к запуску, каждое ядро ​​​​запускается несколько раз, и сообщается среднее арифметическое, минимальная и максимальная пропускная способность.

Как видите, пропускная способность, сообщаемая STREAM, не является реальной пропускной способностью памяти (на аппаратном уровне), поэтому даже не имеет смысла говорить, что это пиковая пропускная способность. Кроме того, она почти всегда намного ниже, чем пиковая пропускная способность. Например, эта статья показывает как страницы ECC и 2 МБ влияют на пропускную способность, о которой сообщает STREAM. Написание эталонного теста, который на самом деле обеспечивает максимально возможную пропускную способность памяти (на аппаратном уровне) на современных процессорах Intel, является серьезной задачей и может быть хорошей задачей для целого доктора философии. Тезис. Однако на практике пиковая пропускная способность менее важна, чем пропускная способность STREAM в домене HPC. (См. также: См. мой ответ для получения информации о проблемах, связанных с измерением пропускной способности памяти на аппаратном уровне.)

Что касается вашего первого вопроса, обратите внимание, что STREAM просто предполагает, что все операции чтения и записи выполняются основной памятью, а не каким-либо кешем. Выделение массива, который намного больше, чем размер LLC, помогает сделать это более вероятным. По сути, необходимо отказаться от сложных и недокументированных аспектов ООО, включая политику замены и политику размещения. Он не обязательно должен быть точно в 4 раза больше, чем LLC. Насколько я понимаю, это то, что доктор Бэндуидт обнаружил на практике.

person Hadi Brais    schedule 11.05.2019