Diese Frage setzt sich auf meiner Frage hier fort (auf Anraten von Mystical):
Wenn ich meine Frage fortsetze, würde der Code, der Intrinsics verwendet, sehr ähnlich aussehen, wenn ich gepackte Anweisungen anstelle von skalaren Anweisungen verwende:
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);
}
Die gemessene Leistung dieses Kernels beträgt ungefähr 5,6 FP-Operationen pro Zyklus, obwohl ich erwarten würde, dass sie genau viermal so hoch ist wie die Leistung der skalaren Version, dh 4,1,6 = 6,4 FP-Operationen pro Zyklus.
Unter Berücksichtigung der Verschiebung des Gewichtsfaktors (danke für den Hinweis) sieht der Zeitplan folgendermaßen aus:
Es sieht so aus, als würde sich der Zeitplan nicht ändern, obwohl es nach der movss
Operation eine zusätzliche Anweisung gibt , die den Skalargewichtswert in das XMM-Register verschiebt und dann shufps
zum Kopieren dieses Skalarwerts in den gesamten Vektor verwendet. Es scheint, dass der Gewichtsvektor bereit ist, für die mulps
Zeit unter Berücksichtigung der Umschaltlatenz von der Last in die Gleitkommadomäne verwendet zu werden, sodass dies keine zusätzliche Latenz verursachen sollte.
Die movaps
(ausgerichtet, verpackt bewegen), addps
und mulps
Anweisungen , die in diesem Kernel (mit Assembler - Code überprüft) verwendet werden , haben die gleiche Latenz & Durchsatz als ihre skalare Versionen, so dass dies keine zusätzliche Latenz entweder entstehen sollte.
Hat jemand eine Idee, wo dieser zusätzliche Zyklus pro 8 Zyklen ausgegeben wird, vorausgesetzt, die maximale Leistung, die dieser Kernel erzielen kann, beträgt 6,4 FP-Operationen pro Zyklus und er läuft mit 5,6 FP-Operationen pro Zyklus?
Übrigens, hier ist, wie die eigentliche Baugruppe aussieht:
…
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
Befehl alle 1,6 Iterationen 1 Zyklus hinzu?" Das ist eine schwierige