Этот вопрос продолжает мой вопрос здесь (по совету Mystical):
Производительность цикла кода 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>
…
shufps
инструкция добавляет 1 цикл каждые 1,6 итераций?» Это сложный вопрос ...