Сколько потери производительности для МОВНЦС? - PullRequest
0 голосов
/ 05 июля 2018

Чтобы выполнить радикальную сортировку для чисел в [0, 2 20 ) на процессоре с 24-килобайтным 6-полосным набором кэшей ассоциативных данных, если выбрана база 2 10 , только 24B кэш может быть предоставлен для каждой цифры, поэтому этот код может привести к большому количеству пропусков кеша:

int *x[1024], c[1024]={0}; 
for(int i=0; i<n; i++)c[A[i]&1023]++;
for(int i=0,s=0; i<1024; i++){x[i]=B+s; s+=c[i];}
for(int i=0; i<n; i++)*(x[A[i]&1023]++)=A[i]; // each ptr require 64B+ cache

Так что я думаю о пропуске кеша и непосредственном сохранении значений в памяти с помощью MOVNTSS или имитации 16B кеша и сохранении с помощью MOVNTPS. Как потери производительности для MOVNTSS и моделирования кеша? Или зависит от чего?

1 Ответ

0 голосов
/ 05 июля 2018

movntss только для AMD (SSE4A) и поддерживается начиная с K10. Это медленнее, чем movntps, однако, в семье Бульдозеров и Райзене. (Один на пропускную способность 4c против одного на 1c для Ryzen's movntps xmm.)

movnti (из целочисленного регистра) имеет ту же пропускную способность, что и movntps xmm на AMD Piledriver (2c), Steamroller (1c) и Ryzen (1c). movnti является частью SSE2, поэтому он доступен (и эффективен) на процессорах Intel.

Ваши числа являются целыми числами (и вы все равно нуждаетесь в них в целочисленных регистрах, чтобы использовать младшие биты в качестве индекса массива), поэтому если вы собираетесь использовать хранилища NT для этого, вы ' d использовать movnti не movntss.


на ЦПУ с 6-полосным кэшем ассоциативных данных с 24-килобайтным набором

Все процессоры с SSE2 имеют гораздо большие кэши L2, которые вам необходимо учитывать. Удар L2 намного быстрее, чем RAM.

Это очень уникальный размер. У вас есть Intel Silvermont или в порядке Atom ( Bonnell или Saltwell ) с 24KB L1D и не менее 512 КиБ. Кэш-память второго уровня (на ядро ​​или совместно используется парой corse).

Но в любом случае, совсем не AMD, поэтому movss никогда не было вариантом. Маломощные Bobcat / Jaguar от AMD имеют нормальные 32-килобайтные L1d-кеши, а их основные ядра имеют 64-килобайтный ( K8 / K10 ), 16-килобайтный (семейство Bulldozer) или 32-килобайтный (Ryzen) L1d-кэши. и все они имеют гораздо большие кэши L2.


Что еще более важно, кэши с обратной записью L1d + L2 будут эффективно комбинировать записи для ваших выходных блоков. Я не думаю, что вы хотите магазины NT вообще.

Вам нужен ваш массив int *x[], чтобы оставаться горячим в L1d, потому что вы читаете, изменяете и пишете его внутри цикла. Но я думаю, что это обычно происходит с обычными алгоритмами кэширования LRU.


Магазины NT ужасны из-за слишком большого количества выходных потоков. Они наиболее эффективны, когда вы можете сохранить полную строку кэша до очистки буфера заполнения строки, что происходит, если подсистеме памяти она нужна для других строк, входящих / выходящих из L1d.

На основной платформе Intel каждое ядро ​​имеет 10 LFB, начиная с Nehalem. Где находится объединяющий запись буфер? x86 . (При гиперпоточности они распределяются между ядрами, но IDK, если это статическое разбиение, например, буфер хранилища, или конкурентное совместное использование, например, сам L1d.)

В основных ядрах (IDK для Atom / Silvermont) хранилища NT имеют большую задержку перед передачей строки кэша на внешние уровни подсистемы памяти ( Enhanced REP MOVSB ​​для memcpy ), но избегание RFO может возможно, будет преимуществом. Вы должны были бы измерить.

Моя самая большая проблема в том, что это было бы ужасно, если бы равнялся любому шаблону в ваших данных, который приводит к множеству не совсем последовательных сохранений в одном сегменте. Шаблон, который L1d могло бы быть поглощено, может быть ужасно с хранилищами NT, которые очищаются до того, как следующее хранилище может присоединиться к нему в буфере объединения записи.


так что этот код может привести к большой потере кэша

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

Затем сортируйте каждое ведро отдельно; в идеале он поместится в кэш L1d.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...