To pytanie jest kontynuacją mojego pytania tutaj (za radą Mistycznego):
Kontynuując moje pytanie, kiedy używam instrukcji spakowanych zamiast instrukcji skalarnych, kod używający funkcji wewnętrznych wyglądałby bardzo podobnie:
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);
}
Zmierzona wydajność tego jądra to około 5,6 operacji FP na cykl, chociaż spodziewałbym się, że będzie to dokładnie 4x wydajność wersji skalarnej, tj. 4,1,6 = 6,4 FP operacji na cykl.
Biorąc pod uwagę zmianę wagi (dzięki za zwrócenie uwagi), harmonogram wygląda następująco:
Wygląda na to, że harmonogram się nie zmienia, chociaż po movss
operacji jest dodatkowa instrukcja, która przenosi wartość wagi skalarnej do rejestru XMM, a następnie używa shufps
do skopiowania tej wartości skalarnej w całym wektorze. Wygląda na to, że wektor wagi jest gotowy do użycia mulps
w czasie, biorąc pod uwagę opóźnienie przełączania z obciążenia do domeny zmiennoprzecinkowej, więc nie powinno to powodować żadnych dodatkowych opóźnień.
movaps
(Wyrównane, pakowane ruch), addps
i mulps
instrukcje, które są używane w tym kernelu (sprawdzony z kodem montażowej) mają taką samą przepustowość jak i opóźnienie ich skalarnych wersji, więc nie powinny ponosić żadnych dodatkowych opóźnień albo.
Czy ktoś ma pomysł, na co wydaje się ten dodatkowy cykl na 8 cykli, zakładając, że maksymalna wydajność tego jądra to 6,4 PR na cykl i działa z szybkością 5,6 PR na cykl?
Przy okazji, oto jak wygląda rzeczywisty montaż:
…
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
instrukcja dodaje 1 cykl na 1,6 iteracji?" To trudne ...