C-кодовая производительность [продолжение]

Этот вопрос продолжается по моему вопросу здесь (по совету Мистика):

Производительность кода кода C


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

for(int i=0; i<size; i+=16) {
    y1 = _mm_load_ps(output[i]);
    …
    y4 = _mm_load_ps(output[i+12]);

    for(k=0; k<ksize; k++){
        for(l=0; l<ksize; l++){
            w  = _mm_set_ps1(weight[i+k+l]);

            x1 = _mm_load_ps(input[i+k+l]);
            y1 = _mm_add_ps(y1,_mm_mul_ps(w,x1));
            …
            x4 = _mm_load_ps(input[i+k+l+12]);
            y4 = _mm_add_ps(y4,_mm_mul_ps(w,x4));
        }
    }
    _mm_store_ps(&output[i],y1);
    …
    _mm_store_ps(&output[i+12],y4);
    }

Измеренная производительность этого ядра составляет около 5,6 операций FP за цикл, хотя я бы ожидал, что это будет ровно 4 раза производительность скалярной версии, то есть 4.1,6 = 6,4 FP ops за цикл.

Принимая во внимание ход весового коэффициента (спасибо, что указали это), график выглядит следующим образом:

schedule

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

Команды movaps (выравнивание, упакованное перемещение), addps и mulps, которые используются в этом ядре (с кодом сборки), имеют такую ​​же задержку и пропускную способность, что и их скалярные версии, поэтому это не должно нести дополнительную задержку.

Есть ли у кого-нибудь идея, где этот дополнительный цикл на 8 циклов расходуется, если предположить, что максимальная производительность, которую может получить это ядро, составляет 6.4 FP ops за цикл и работает на 5.6 FP ops за такт?


Кстати, вот как выглядит фактическая сборка:

…
Block x: 
  movapsx  (%rax,%rcx,4), %xmm0
  movapsx  0x10(%rax,%rcx,4), %xmm1
  movapsx  0x20(%rax,%rcx,4), %xmm2
  movapsx  0x30(%rax,%rcx,4), %xmm3
  movssl  (%rdx,%rcx,4), %xmm4
  inc %rcx
  shufps $0x0, %xmm4, %xmm4               {fill weight vector}
  cmp $0x32, %rcx 
  mulps %xmm4, %xmm0 
  mulps %xmm4, %xmm1
  mulps %xmm4, %xmm2 
  mulps %xmm3, %xmm4
  addps %xmm0, %xmm5 
  addps %xmm1, %xmm6 
  addps %xmm2, %xmm7 
  addps %xmm4, %xmm8 
  jl 0x401ad6 <Block x> 
…

Ответ 1

Попробуйте использовать профилирование EMON в Vtune или какой-то эквивалентный инструмент, например oprof

EMON (мониторинг событий) profiling = > как инструмент, основанный на времени, но он может рассказать вам, какое событие производительности вызывает проблему. Хотя, сначала вы должны начать с профиля, основанного на времени, чтобы узнать, выдается ли какая-то конкретная инструкция. (И, возможно, связанные события, которые рассказывают вам, как часто на этом IP-телефоне был выход на пенсию).

Чтобы использовать профилирование EMON, вы должны просмотреть список событий, начиная от "обычных подозреваемых" до...

Здесь я бы начал с промахов кеша, выравнивания. Я не знаю, имеет ли процессор, который у вас есть, счетчик ограничений для портов USB - это должно быть, но я недавно добавил EMON-профилирование, и я не знаю, насколько хорошо они поддерживают, добавляя события, подходящие для микроархитектуры.

Возможно также, что это внешний интерфейс, выбор команды, остановка. Сколько байтов в этих инструкциях, во всяком случае? Для этого есть события EMON.


Отвечая на комментарий, Nehalem VTune не может видеть события L3: не верно. Вот материал, который я добавлял в комментарий, но не подходил:

На самом деле, есть счетчики производительности для LL3/L3 $/так называемого Uncore. Я был бы очень удивлен, если VTune не поддержит их. См. http://software.intel.com/sites/products/collateral/hpc/vtune/performance_analysis_guide.pdf указывает на VTune и другие инструменты, такие как PTU. Фактически, даже без событий LL3, как говорит Дэвид Левинталь, "процессор Intel® Core ™ i7 имеет" событие латентности ", которое очень похоже на событие EAR семейства данных Itanium®. Эти примеры загружает, записывает количество циклов между выполнением инструкции и фактическими доставлять данные. Если измеренная задержка больше минимальной задержки запрограммирован в MSR 0x3f6, бит 15: 0, тогда счетчик увеличивается. счетчик переполняет оружие механизмом PEBS и на следующем событии, удовлетворяющем задержке порог, измеренная задержка, виртуальный или линейный адрес и источник данных скопированы в 3 дополнительных регистра в буфере PEBS. Поскольку виртуальный адрес захваченный в известное местоположение, драйвер выборки также может выполнять виртуальную физический перевод и захват физического адреса. Физический адрес идентифицирует NUMA и, в принципе, позволяет анализировать сведения о кеше "Он также указывает на стр. 35 на события VTune, такие как L3 CACHE_HIT_UNCORE_HIT и L3 CACHE_MISS_REMOTE_DRAM. Иногда вам нужно искать числовые коды и программировать их в интерфейсе более низкого уровня VTune, но я думаю, что в этом случае это видно в симпатичный пользовательский интерфейс.


ОК, в http://software.intel.com/en-us/forums/showthread.php?t=77700&o=d&s=lr программа VTune в России (я думаю) "объясняет", что вы не можете пробовать на события Uncore.

Он ошибался - вы могли бы, например, включить только один процессор, и образец осмысленно. Я также считаю, что есть возможность отмечать отсутствующие данные L3, когда он возвращается в CPU. Фактически, в целом L3 знает, к какому процессору возвращаются данные, поэтому вы можете определенно пробовать. Возможно, вы не знаете, какой гиперпоток, но снова можете отключить, перейдите в режим одиночного потока.

Но похоже, что, как это обычно бывает, вам нужно будет работать над проектом, но не с этим, чтобы сделать это.

Сначала попробуйте профилировать латентность. Это полностью внутри CPU, и люди VTune вряд ли перепутали бы его слишком много.

И, повторяю, вероятность того, что ваша проблема находится в ядре, а не в L3. Поэтому VTune не может справиться с этим.


Попробуйте "Учет циклов" для Levinthal.