C代码循环性能[续]

C代码循环性能[续],c,performance,intel,instructions,assembly,C,Performance,Intel,Instructions,Assembly,这个问题继续我的问题(根据神秘主义者的建议): 继续我的问题,当我使用压缩指令而不是标量指令时,使用内部函数的代码看起来非常相似: 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++){

这个问题继续我的问题(根据神秘主义者的建议):


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

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);
    }

尝试在Vtune中使用EMON评测,或使用类似于oprof的工具

  • (您可以搜索Windows版本)
EMON(Event Monitoring)profiling=>类似于基于时间的工具,但它可以告诉您是什么性能事件导致了问题。不过,您应该首先从基于时间的概要文件开始,以查看是否有特定的指令跳出。(可能还有相关的事件,告诉你在该IP上有一个退休摊位的频率。)

要使用EMON评测,您必须运行一系列事件,从“常见嫌疑犯”到

在这里,我将从缓存未命中、对齐开始。我不知道您使用的处理器是否有RF端口限制计数器-它应该有-但我很久以前就添加了EMON评测,我不知道它们通过添加适合微体系结构的事件来保持的状态

也可能是前端、指令提取、暂停。这些指令中有多少字节?这方面也有EMON活动


回应Nehalem VTune无法看到三级事件的评论:不正确。以下是我在评论中添加的内容,但不适合:


实际上,对于LL3/L3$/所谓的Uncore,存在性能计数器。如果VTune不支持它们,我会非常惊讶。请参阅VTune和其他工具(如PTU)的要点。事实上,即使没有LL3事件,正如David Levinthal所说:“Intel®Core™ i7处理器有一个“延迟事件”,它是 与安腾处理器系列数据EAR事件非常相似。此事件示例 加载,记录指令执行和实际执行之间的周期数 交付数据。如果测量的延迟大于最小延迟 编程到MSR 0x3f6,位15:0,然后计数器递增。计数器 溢出保护PEBS机制,并在满足延迟的下一个事件上溢出 阈值、测量的延迟、虚拟或线性地址以及数据源 复制到PEBS缓冲区中的3个附加寄存器中。因为虚拟地址为 捕获到已知位置后,采样驱动程序还可以执行虚拟到 物理转换和捕获物理地址。物理地址标识 NUMA home location原则上允许分析缓存的详细信息 在第35页,他还指出了VTune事件,如三级缓存命中未命中远程DRAM。有时您需要查找数字代码并将其编程到VTune的低级界面中,但我认为在这种情况下,它在漂亮的用户界面中是可见的


好的,在俄罗斯的一个VTune程序员(我认为)中,“解释”了您不能对非核心事件进行采样

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

但看起来,要做到这一点,您必须绕过VTune,而不是使用它,这是很常见的

首先尝试延迟分析。这完全在CPU内部,VTune人员不太可能把它搞得太糟

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



试试Levinthal的“循环记帐”吧。

所以我想现在的问题是:“为什么
shufps
指令每1.6次迭代添加一个循环?”这是一个困难的问题…我希望它没有开销,因为
shufps
的输出应该直接可用于
multps
op,因为这两个FP域都很容易找到。确保权重向量不包含任何非规范化值。尝试不使用shuffle指令的循环。它不会产生任何有用的结果,但可能您会发现哪个指令会花费额外的周期(当然,我怀疑是洗牌)。@Mystical:我看到每次循环迭代增加0.75个周期。(这不是我关于使用5个周期而不是4个周期的评论,这会让你找到答案…:-)首先,现在你要求4倍的缓存带宽。数据大小有多大?它们适合一级缓存吗?谢谢你的反应。我使用VTune分析应用程序,但nehalem体系结构的问题是,三级缓存属于内核的
非内核部分,因此此部分没有可用的性能事件计数器。因此,很难估计缓存未命中率等。实际上,LL3/L3$/所谓的Uncore有性能计数器。如果VTune不支持它们,我会非常惊讶。看,我写了比评论内容更多的内容,试图将其移至答案并清理原始评论,但评论只能编辑5分钟。简短版本:VTune允许您查看三级缓存未命中。即使没有Uncore支持,也可以使用延迟分析——而且它有Uncore支持。总体而言,我怀疑您的问题不是三级缓存未命中。更像是前端事件。@KrazyGlew:你猜得对,他是一个来自俄罗斯联邦的俄罗斯人。这是他在LinkedIn上的个人资料-
…
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> 
…