这个问题继续在这里我的问题(根据神秘的建议) :
继续我的问题,当我使用打包指令而不是标量指令时,使用内部函数的代码看起来非常相似:
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>
…