У меня в приложении многократно добавлено ядро, и я хочу повысить его производительность.
Я использую Intel Core i7-960 (тактовая частота 3,2 ГГц) и уже вручную внедрил ядро с использованием встроенных функций SSE:
for(int i=0; i<iterations; i+=4) {
y1 = _mm_set_ss(output[i]);
y2 = _mm_set_ss(output[i+1]);
y3 = _mm_set_ss(output[i+2]);
y4 = _mm_set_ss(output[i+3]);
for(k=0; k<ksize; k++){
for(l=0; l<ksize; l++){
w = _mm_set_ss(weight[i+k+l]);
x1 = _mm_set_ss(input[i+k+l]);
y1 = _mm_add_ss(y1,_mm_mul_ss(w,x1));
…
x4 = _mm_set_ss(input[i+k+l+3]);
y4 = _mm_add_ss(y4,_mm_mul_ss(w,x4));
}
}
_mm_store_ss(&output[i],y1);
_mm_store_ss(&output[i+1],y2);
_mm_store_ss(&output[i+2],y3);
_mm_store_ss(&output[i+3],y4);
}
Я знаю, что могу использовать упакованные векторы fp дляувеличить производительность, и я уже сделал это успешно, но я хочу знать, почему один скалярный код не может удовлетворить пиковую производительность процессора.
Производительность этого ядра на моей машине составляет ~ 1.6 операций FP за цикл, в то время как максимум будет составлять 2 операции FP за цикл (поскольку FP add + FP mul может выполняться параллельно).
Если я не ошибаюсь в изучении сгенерированного ассемблерного кода, идеальное расписание будет выглядеть следующим образом, где инструкция mov
занимает 3 цикла, задержка переключения с домена загрузки на домен FP для зависимогоинструкция занимает 2 цикла, умножение FP - 4 цикла, а добавление FP - 3 цикла.(Обратите внимание, что зависимость от умножения -> сложение не приводит к задержке переключения, поскольку операции принадлежат одному домену).
В соответствии с измеренной производительностью (~80% от максимальной теоретической производительности) накладные расходы составляют ~ 3 инструкции на 8 циклов.
Я пытаюсь либо:
- избавиться от этих накладных расходов, либо
- объяснить, откуда они
КонечноСуществует проблема с пропуском кеша и смещением данных, которые могут увеличить задержку команд перемещения, но есть ли другие факторы, которые могут играть роль здесь?Как регистр чтения киосков или что-то?
Я надеюсь, что моя проблема ясна, заранее спасибо за ваши ответы!
Обновление: сборка внутреннего цикла выглядит следующим образом:
...
Block 21:
movssl (%rsi,%rdi,4), %xmm4
movssl (%rcx,%rdi,4), %xmm0
movssl 0x4(%rcx,%rdi,4), %xmm1
movssl 0x8(%rcx,%rdi,4), %xmm2
movssl 0xc(%rcx,%rdi,4), %xmm3
inc %rdi
mulss %xmm4, %xmm0
cmp $0x32, %rdi
mulss %xmm4, %xmm1
mulss %xmm4, %xmm2
mulss %xmm3, %xmm4
addss %xmm0, %xmm5
addss %xmm1, %xmm6
addss %xmm2, %xmm7
addss %xmm4, %xmm8
jl 0x401b52 <Block 21>
...