Почему этот спецполин не работает на озере Каби?

Я пытаюсь создать на мой Kabe lake 7600U, я использую CentOS 7.

Полный тестовый репозиторий доступен на GitHub.

Моя версия спецполина выглядит следующим образом (cfr. spec.asm ):

specpoline:
        ;Long dependancy chain
        fld1
        TIMES 4 f2xm1
        fcos
        TIMES 4 f2xm1
        fcos
        TIMES 4 f2xm1

        %ifdef ARCH_STORE
            mov DWORD [buffer], 241     ;Store in the first line
        %endif

        add rsp, 8
        ret

Эта версия отличается от версии Генри Вонга тем, что поток отклоняется на архитектурный путь. В то время как исходная версия использовала фиксированный адрес, я передаю цель в стек.
Таким образом, add rsp, 8 удалит исходный адрес возврата и использует искусственный.

В первой части функции я создаю длинную цепочку зависимостей с задержкой, используя некоторые старые инструкции FPU, затем независимую цепочку, которая пытается обмануть предсказатель стека возврата ЦП.


Описание кода

Спецполин вставляется в контекст профилирования с помощью FLUSH+RELOAD1, тот же файл сборки также содержит:

buffer

Непрерывный буфер, охватывающий 256 отдельных строк кэша, каждая из которых разделена GAP-1 строками, всего 256*64*GAP байт.

GAP используется для предотвращения аппаратной предварительной выборки.

Далее следует графическое изображение (каждый индекс идет сразу после другого).

Буфер F+R

timings

Массив из 256 DWORD, каждая запись содержит время в циклах ядра, необходимое для доступа к соответствующей строке в буфере F+R.

flush

Небольшая функция для касания каждой страницы (с сохранением, просто чтобы убедиться, что COW на нашей стороне) буфера F+R и вытеснения обозначенных строк.

'профиль'

Стандартная функция профиля, которая использует lfence+rdtsc+lence скважину для профилирования нагрузки от каждой линии в буфере F+R и сохраняет результат в массиве timings.

leak

Это функция, которая выполняет настоящую работу, вызовите функцию specpoline, помещающую хранилище в спекулятивный путь, и функцию profile в архитектурный путь.

;Flush the F+R lines
        call flush

        ;Unaligned stack, don't mind
        lea rax, [.profile]
        push rax
        call specpoline

        ;O.O 0
        ; o o o SPECULATIVE PATH
        ;0.0 O

        %ifdef SPEC_STORE
            mov DWORD [buffer], 241        ;Just a number
        %endif

        ud2                             ;Stop speculation

   .profile:
        ;Ll Ll
        ;  !  !  ARCHITECTURAL PATH
        ;Ll Ll
        
        ;Fill the timings array
        call profile

Для начальной загрузки тестовой системы используется небольшая программа на C.

Запуск тестов

В коде используются условные препроцессоры для условного помещения хранилища в архитектурный путь (фактически в саму спецификацию), если определено ARCH_STORE, и для условного помещения хранилища в спекулятивный путь, если определено SPEC_STORE.

Оба сохраняют доступ к первой строке буфера F+R.

Запуск make run_spec и make run_arch соберет spec.asm с соответствующим символом, скомпилирует тест и запустит его.

Тест показывает тайминги для каждой строки буфера F+R.

Сохранить в архитектурном пути

 38    230    258    250    212    355    230    223    214    212    220    216    206    212    212    234
213    222    216    212    212    210   1279    222    226    301    258    217    208    212    208    212
208    208    208    216    210    212    214    213    211    213    254    216    210    224    211    209
258    212    214    224    220    227    222    224    208    212    212    210    210    224    213    213
207    212    254    224    209    326    225    216    216    224    214    210    208    222    213    236
234    208    210    222    228    223    208    210    220    212    258    223    210    218    210    218
210    218    212    214    208    209    209    225    206    208    206   1385    207    226    220    208
224    212    228    213    209    226    226    210    226    212    228    222    226    214    230    212
230    211    226    218    228    212    234    223    228    216    228    212    224    225    228    226
228    242    268    226    226    229    224    226    224    212    299    216    228    211    226    212
230    216    228    224    228    216    228    218    228    218    227    226    230    222    230    225
228    226    224    218    225    252    238    220    229   1298    228    216    228    208    230    225
226    224    226    210    238    209    234    224    226    255    230    226    230    206    227    209
226    224    228    226    223    246    234    226    227    228    230    216    228    211    238    216
228    222    226    227    226    240    236    225    226    212    226    226    226    223    228    224
228    224    229    214    224    226    224    218    229    238    234    226    225    240    236    210

Хранить на предполагаемом пути

298    216    212    205    205   1286    206    206    208    251    204    206    206    208    208    208
206    206    230    204    206    208    208    208    210    206    202    208    206    204    256    208
206    208    203    206    206    206    206    206    208    209    209    256    202    204    206    210
252    208    216    206    204    206    252    232    218    208    210    206    206    206    212    206
206    206    206    242    207    209    246    206    206    208    210    208    204    208    206    204
204    204    206    210    206    208    208    232    230    208    204    210   1287    204    238    207
207    211    205    282    202    206    212    208    206    206    204    206    206    210    232    209
205    207    207    211    205    207    209    205    205    211    250    206    208    210    278    242
206    208    204    206    208    204    208    210    206    206    206    206    206    208    204    210
206    206    208    242    206    208    206    208    208    210    210    210    202    232    205    207
209    207    211    209    207    209    212    206    232    208    210    244    204    208    255    208
204    210    206    206    206   1383    209    209    205    209    205    246    206    210    208    208
206    206    204    204    208    246    206    206    204    234    207    244    206    206    208    206
208    206    206    206    206    212    204    208    208    202    208    208    208    208    206    208
250    208    214    206    206    206    206    208    203    279    230    206    206    210    242    209
209    205    211    213    207    207    209    207    207    211    205    203    207    209    209    207

Поставил хранилище в архитектурный путь для проверки функции таймингов, вроде работает.

Однако я не могу получить тот же результат с хранилищем на спекулятивном пути.

Почему ЦП не выполняет хранилище спекулятивно?


1 Признаюсь, я никогда не тратил время на изучение всех методов профилирования кеша. Надеюсь, я использовал правильное имя. Под FLUSH+RELOAD я подразумеваю процесс вытеснения набора строк, спекулятивного выполнения некоторого кода, а затем записи времени доступа к каждой из вытесненных строк.


person Margaret Bloom    schedule 05.04.2019    source источник
comment
Ваша длинная цепочка отложений составляет много операций от этих микрокодированных инструкций x87. fcos составляет 53-105 мкОп на SKL, с пропускной способностью 50-130 тактов. Таким образом, это около 1 цикла на задержку моп. Если вам нужна наибольшая задержка от мопов, которые вписываются в RS, цепочка зависимостей sqrtpd, вероятно, будет вашим лучшим выбором.   -  person Peter Cordes    schedule 06.04.2019
comment
@PeterCordes Сначала я использовал sqrtpd с аналогичными результатами. Однако я не инициализировал регистр XMM, используемый в качестве ввода (и вывода), думая, что это не имеет значения. Я проверил еще раз, но на этот раз я инициализировал регистр двумя двойными значениями 1e200, и то, что я получаю, является прерывистым результатом. Иногда строка выбирается спекулятивно, иногда нет. Похоже, что movups xmm0, [...], за которыми следуют десять sqrtpd xmm0, xmm0, является лучшей комбинацией, хотя и не на 100% надежной. Здесь немного поздно, я обновлю ответ завтра. Спасибо за отзыв!   -  person Margaret Bloom    schedule 06.04.2019


Ответы (1)


Ваша «длинная цепочка отложений» - это много операций от этих микрокодированных инструкций x87. fcos составляет 53-105 мксек на SKL, с пропускной способностью 50-130 тактов. Таким образом, это около 1 цикла на задержку uop, а планировщик / станция резервирования (RS) «только» имеет 97 записей в SKL / KBL. Кроме того, получение более поздних инструкций в неупорядоченной серверной части может быть проблемой, потому что микрокод берет на себя внешний интерфейс и нуждается в каком-то механизме, чтобы решить, какие мопы выдавать дальше, вероятно, в зависимости от результата некоторых вычислений. (Известно, что количество мопов зависит от данных.)

Если вам нужна наибольшая задержка от RS, полной невыполненных мопов, цепочка зависимостей sqrtpd, вероятно, ваш лучший выбор. например

    xorps  xmm0,xmm0                   ; avoid subnormals that might trigger FP assists
    times 40 sqrtsd xmm0, xmm0

    ; then make the store of the new ret addr dependent on that chain
    movd   ebx, xmm0
    ; and  ebx, 0            ; not needed, sqrt(0) = 0.0 = integer bit pattern 0
    mov [rsp+rbx], rax
    ret

Начиная с Nehalem, процессоры Intel имеют быстрое восстановление для пропущенных ветвей с буфером порядка ветвлений, который фиксирует состояние OoO (включая RAT и, возможно, RS) Что именно происходит когда процессор Skylake неверно предсказывает ветвь?. Поэтому они могут восстановиться точно до ошибочного прогноза, не дожидаясь, пока ошибочный прогноз станет состоянием вывода из эксплуатации.

mov [rsp], rax может выполняться, как только он входит в RS, или, по крайней мере, без зависимости от цепочки sqrt dep. Как только store-forwarding сможет создать значение, ret uop сможет выполнить и проверить предсказание, а также обнаружить неверное предсказание, пока цепочка sqrt dep все еще работает. (ret — это 1 микроплавкий моп для портов загрузки + порт 6, где находится исполнительный блок взятия ветвей.)

Связывание цепочки dep sqrtsd с сохранением нового адреса возврата предотвращает преждевременное выполнение ret. Выполнение ret uop в порту выполнения = проверка прогноза и обнаружение ошибочного прогноза, если таковой имеется.

(В отличие от Meltdown, где «неправильный» путь продолжает работать до тех пор, пока сбойная нагрузка не достигнет вывода из эксплуатации, и вы хотите выполнить его как можно скорее (просто не выключать). Но обычно вы хотите провести целую атаку Meltdown в тени чего-то другого, например, TSX или спецполина, и в этом случае вам понадобится что-то подобное, и весь расплав будет в тени этой цепочки отложений. Тогда Meltdown не понадобится собственный sqrtsd отп цепочка.)


(vsqrtpd ymm по-прежнему составляет 1 мкп на SKL, с худшей пропускной способностью, чем xmm, но с той же задержкой. Поэтому используйте sqrtsd, потому что он такой же длины и предположительно более энергоэффективен.)

В лучшем случае задержка составляет 15 циклов, а в худшем — 16 на SKL/KBL (https://agner.org/optimize), так что вряд ли имеет значение, с каких входных данных вы начнете.


Сначала я использовал sqrtpd с аналогичными результатами. Однако я не инициализировал регистр XMM, используемый в качестве ввода (и вывода), думая, что это не имеет значения. Я снова протестировал, но на этот раз я инициализировал регистр двумя двойными значениями 1e200, и то, что я получаю, является прерывистым результатом. Иногда строка выбирается спекулятивно, иногда нет.

Если XMM0 содержит субнормальное значение (например, битовый шаблон представляет собой небольшое целое число), sqrtpd использует помощь микрокода. (fp_assist.any счетчик производительности). Даже если результат нормальный, но ввод субнормальный. Я протестировал оба случая на SKL с помощью этого цикла:

  pcmpeqd   xmm0,xmm0
  psrlq     xmm0, 61        ; or 31 for a subnormal input whose sqrt is normalized
  addpd     xmm0,xmm0       ; avoid domain-crossing vec-int -> vec-fp weirdness

  mov   ecx, 10000000
.loop:
    sqrtpd  xmm1, xmm0
    dec    ecx
    jnz   .loop

 mov eax,1
 int 0x80   ; sys_exit

perf stat -etask-clock,context-switches,cpu-migrations,page-faults,cycles,branches,instructions,uops_issued.any,uops_executed.thread,fp_assist.any показывает 1 ассист на итерацию для ненормальных входных данных с выдачей 951M мкп (и ~160 циклов на итерацию). Таким образом, мы можем сделать вывод, что помощь микрокода для sqrtpd в этом случае занимает ~95 мкОм, а пропускная способность составляет ~160 циклов, когда это происходит последовательно.

по сравнению с 20M uops, выпущенными для ввода, = NaN (все единицы), с 4,5 циклами на итерацию. (Цикл выполняет 10M sqrtpd uops и 10M макросплавленных dec/jcc uops.)

person Peter Cordes    schedule 05.04.2019
comment
Я получаю гораздо более последовательные результаты, заменяя add rsp, 8 хранилищем на [rsp], чтобы отвлечь выполнение. Как и Генри Вонг. Возможно какое-то несовершенное расписание add или что-то в этом роде, IDK. В любом случае ваши наблюдения мне очень помогли. - person Margaret Bloom; 06.04.2019
comment
На самом деле мне пришлось создать единую цепочку зависимостей с xorps xmm0, xmm0 / TIMES 10 sqrtpd xmm0, xmm0 / movq rbx, xmm0 / mov [rsp+rbx], rax / ret. Я предполагаю, что в противном случае ЦП выполняет сохранение в [rsp] слишком рано и исправляет прогноз предиктора стека возврата до того, как спекулятивный путь будет выполнен слишком далеко. - person Margaret Bloom; 06.04.2019
comment
@MargaretBloom: Ах, верно. Начиная с Nehalem, процессоры Intel обеспечивают быстрое восстановление пропущенных ветвей с помощью буфера порядка ветвлений, который фиксирует состояние OoO (включая RAT и, возможно, RS). Skylake CPU неверно предсказывает ветку?. Таким образом, он может восстановиться точно до ошибочного прогноза, не дожидаясь, пока ошибочный прогноз станет состоянием выхода на пенсию. Я не очень внимательно следил за тем, что вы делаете; с Meltdown неправильный путь продолжает работать до тех пор, пока неисправная нагрузка не достигнет выхода на пенсию, но здесь это не так. - person Peter Cordes; 06.04.2019
comment
@MargaretBloom: обновил мой ответ, спасибо за подробности о том, что сработало. - person Peter Cordes; 06.04.2019