C 代码循环性能[继续]

这个问题继续在这里我的问题(根据神秘的建议) :

C 代码循环性能


继续我的问题,当我使用打包指令而不是标量指令时,使用内部函数的代码看起来非常相似:

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 操作。

考虑到体重因素的变化(谢谢指出) ,时间表看起来是这样的:

schedule

虽然在 movss操作之后有一个额外的指令,将标量权重值移动到 XMM 寄存器,然后使用 shufps在整个向量中复制这个标量值,但是看起来计划并没有改变。权重向量似乎已经准备好及时用于 mulps,考虑到从负载到浮点域的切换延迟,因此这不应该产生任何额外的延迟。

这个内核中使用的 movaps(对齐、打包移动)、 addpsmulps指令(用汇编代码检查)与它们的标量版本具有相同的延迟和吞吐量,所以这也不会产生任何额外的延迟。

有没有人知道每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>
…
5014 次浏览

尝试在 Vtune 使用 EMON 分析,或者一些类似的工具,比如 oporof

EMON (事件监视)分析 = > 就像一个基于时间的工具,但是它可以告诉您是什么性能事件导致了问题。尽管如此,您应该首先使用基于时间的配置文件开始,以查看是否有一个特定的指令跳出来。(可能还有一些相关事件,告诉你这个 IP 地址多久会出现一次退休故障。)

要使用 EMON 分析,您必须运行一个事件列表,范围从“通常的嫌疑人”到..。

在这里,我会从缓存未命中,校准开始。我不知道你正在使用的处理器是否有一个计数器来应对射频端口的限制——它应该有——但是我很久以前就加入了 EMON 配置文件,我不知道他们通过添加适合微架构的事件来保持得如何。

它也可能是一个前端,指令获取,失速。这些指令到底有多少字节?也有 EMON 事件。


回应 Nehalem VTune 看不到 L3事件的评论: 不正确。下面是我在评论中添加的一些内容,但并不适合:

实际上,对于 LL3/L3 $/所谓的 Uncore,存在性能计数器。如果 VTune 不支持他们,我会非常惊讶。参见 http://software.intel.com/sites/products/collateral/hpc/vtune/performance_analysis_guide.pdf指向 VTune 和其他工具,如 PTU。事实上,即使没有 LL3事件,正如 David Levinthal 所说: “ Intel CoreTM i7处理器有一个“延迟事件”,即 非常类似于 Itanium 处理器系列数据 EAR 事件 负载,记录指令执行和实际执行之间的周期数 如果测量的延迟大于最小延迟,则为 编程到 MSR 0x3f6,位15:0,然后计数器是递增的。计数器 溢出武装 PEBS 机制,并在下一个事件上满足延迟 阈值,测量的延迟,虚拟或线性地址和数据源是 复制到 PEBS 缓冲区中的另外3个寄存器中 捕获到一个已知的位置,采样驱动程序还可以执行一个虚拟的 物理翻译并捕获物理地址。物理地址标识 NUMA 主位置原则上允许分析缓存的细节 入住率。”他还指出,在第35页,VTune 事件,如 L3 CACHE _ HIT _ UNCORE _ HIT 和 L3 CACHE _ MISS _ REMOTE _ DRAM。有时您需要查找数字代码并将它们编入 VTune 的低级界面,但我认为在这种情况下,它在漂亮的用户界面中是可见的。


好的,在 http://software.intel.com/en-us/forums/showthread.php?t=77700&o=d&s=lr中,俄罗斯的一个 VTune 程序员(我认为)“解释”了你不能在 Uncore 事件上取样。

他错了——例如,您可以只启用一个 CPU,并有意义地采样。我还相信,当 L3返回到 CPU 时,可以标记丢失的数据。实际上,L3总体上知道将数据返回给哪个 CPU,因此您可以明确地进行采样。您可能不知道哪个超线程,但是您可以再次禁用,进入单线程模式。

但是看起来,正如很常见的那样,您必须围绕 VTune 工作,而不是使用它,才能做到这一点。

先试试潜伏期分析。这完全在中央处理器内部,而且 VTune 的人不太可能把它搞得太糟。

我再说一遍,很可能你的问题在核心,而不是 L3。所以 VTune 应该能够处理这个问题。


试试每个 Levinthal 的“循环会计”。