Производительность цикла кода C [продолжение]
Этот вопрос продолжается по моему вопросу здесь (по совету Мистического):
Производительность цикла кода C
В продолжение моего вопроса, когда я использую упакованные инструкции вместо скалярных инструкций, код с использованием встроенных функций будет выглядеть очень похоже:
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 за такт.
С учетом изменения весового коэффициента (спасибо за указание на это), график выглядит следующим образом:
Похоже, что расписание не меняется, хотя после movss
операция, которая перемещает скалярное значение веса в регистр XMM, а затем использует shufps
скопировать это скалярное значение во всем векторе. Кажется, что весовой вектор готов к использованию для mulps
вовремя принимая во внимание задержку переключения с нагрузки на домен с плавающей запятой, так что это не должно вызывать дополнительной задержки.
movaps
(выровненный, упакованный ход),addps
& mulps
инструкции, используемые в этом ядре (проверенные с помощью ассемблерного кода), имеют такую же задержку и пропускную способность, что и их скалярные версии, поэтому это также не должно вызывать дополнительной задержки.
У кого-нибудь есть идея, на что тратится этот дополнительный цикл на 8 циклов, предполагая, что максимальная производительность, которую может получить это ядро, составляет 6,4 FP операций за такт, а скорость его работы составляет 5,6 FP операций на такт?
Кстати вот как выглядит фактическая сборка:
…
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
- Vtune для Linux (вы можете найти версию для Windows)
- OProfile
EMON (Event Monitoring) profiling => похож на инструмент, основанный на времени, но он может сказать вам, какое событие производительности вызывает проблему. Хотя сначала вы должны начать с профиля, основанного на времени, чтобы увидеть, выпадает ли какая-то конкретная инструкция. (И, возможно, связанные с этим события, которые говорят вам о том, как часто на этом IP происходил выход на пенсию)
Чтобы использовать профилирование EMON, вы должны просмотреть список событий, начиная от "обычных подозреваемых" до…
Здесь я бы начал с промахов кэша, выравнивания. Я не знаю, есть ли у используемого вами счетчика счетчик ограничений RF-порта - он должен - но я давно добавил профилирование EMON, и я не знаю, насколько хорошо они справляются, добавляя события, подходящие для микроархитектуры.
Также возможно, что это внешний интерфейс, выборка команд, остановка. В любом случае, сколько байтов в этих инструкциях? Для этого тоже есть события EMON.
Отвечая на комментарий, что Nehalem VTune не может видеть события L3: не верно. Вот что я добавлял в комментарии, но не подходил:
На самом деле, есть счетчики производительности ARE для 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 знает, на какой процессор он возвращает данные, так что вы можете определенно выполнить выборку. Вы можете не знать, какая гиперпотока, но опять же вы можете отключить, перейти в однопотоковый режим.
Но, похоже, что, как правило, вам придется работать вокруг VTune, а не с ним, чтобы сделать это.
Сначала попробуйте профилирование задержки. Это полностью внутри процессора, и маловероятно, что люди VTune испортили его слишком сильно.
И, еще раз говорю, вероятность того, что ваша проблема в ядре, а не в L3. Так что VTune должен быть в состоянии справиться с этим.
Попробуйте "Учет циклов" за Левинталь.