这个问题继续我的问题here(根据Mystical的建议):
继续我的问题,当我使用打包指令而不是标量指令时,使用内在函数的代码看起来非常相似:
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指令(用汇编代码检查)具有与其标量版本相同的延迟和吞吐量,因此这也不应该产生任何额外的延迟。
假设这个内核可以获得的最大性能是每个周期 6.4 FP ops 并且它以每个周期 5.6 FP ops 运行,是否有人知道每 8 个周期的这个额外周期花在哪里?
顺便说一下,这里是实际装配的样子:
…
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> 
…