2012-04-04 9 views
83

Этот вопрос продолжает на мой вопрос здесь (по совету мистического):C производительность кода цикла [продолжение]

C code loop performance


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

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 ОПП за цикл.

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

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> 
… 
+0

Итак, теперь я задаю вопрос: «Почему инструкция' shufps »добавляет 1 цикл каждые 1.6 итерации?» Это сложно ... – Mysticial

+0

Я бы ожидал, что у него не будет накладных расходов, так как вывод 'shufps' должен быть непосредственно доступен для' multps' op, так как он является доменом FP ​​ – Ricky

+0

Легко узнать. Убедитесь, что вектор весов не содержит значений денормализованных значений. Попробуйте цикл без инструкции перетасовки.Это не принесет каких-либо полезных результатов, но, может быть, ваша находка, какая инструкция требует дополнительных циклов (я подозреваю, что тасовка, конечно). – hirschhornsalz

ответ

3

Попробуйте использовать 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® Processor. Эти примеры событий загружают, записывая количество циклов между выполнением команды и фактическим доставлять данные. Если измеренная задержка больше минимальной задержки , запрограммированной в MSR 0x3f6, бит 15: 0, то счетчик увеличивается. Счетчик переполняет оружие PEBS механизм и на следующем событии, удовлетворяющем задержке , измеренная задержка, виртуальный или линейный адрес и источник данных , скопированные в 3 дополнительных регистра в буфере PEBS. Поскольку виртуальный адрес , записанный в известное местоположение, e, также может выполнять виртуальный физический перевод и фиксировать физический адрес. Физический адрес идентифицирует исходное местоположение 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.

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

Но похоже, что, как это обычно бывает, вам придется работать ВОКРУГ VTune, а не с этим, для этого.

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

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


Попробуйте «Циклический учет» за Levinthal.

+0

Спасибо за вашу реакцию. Я использую VTune для анализа моего приложения, но проблема с архитектурой nehalem заключается в том, что кэш L3 относится к «вне ядра» части ядра, поэтому для этой части нет счетчиков событий производительности. Поэтому сложно оценить пропуски кэша и т. Д. – Ricky

+0

На самом деле, есть счетчики производительности для LL3/L3 $/так называемого Uncore. Я был бы очень удивлен, если VTune не поддержит их. См. Http://software.intel.com/sites/products/collateral/hpc/vtune/performance_analysis_guide.pdf –

+0

Я написал больше, чем вписывался в комментарий, пытался переместить его в ответ и очистить исходный комментарий, но комментарии может редактировать только 5 минут в течение 5 минут. Короткая версия: VTune позволяет видеть промахи кэша L3. Даже без поддержки Uncore, используя латентное профилирование, и имеет поддержку Uncore. –