用不同的内核版本分析性能回归的原因

时间:2014-01-08 14:01:04

标签: performance linux-kernel perf radiance

我在x86_64系统上遇到了从Linux内核3.11到3.12的奇怪性能回归。 在Fedora 20上运行Mark Stock's Radiance benchmark,3.12明显变慢。没有其他任何改变 - 相同的二进制,相同的glibc - 我只是启动一个不同的内核版本,性能改变。 定时程序rpict是1​​00%CPU绑定的用户级代码。

在我将此报告为错误之前,我想找到导致此行为的原因。我对Linux内核了解不多,而从3.11到3.12的更改日志并没有给我任何线索。

我在两个系统上观察到这一点,Intel Haswell(i7-4771)和AMD Richland(A8-6600K)。 在Haswell系统上,用户时间从895秒变为3.11到962变为3.12。在里奇兰,从1764年到1844年。这些时间可以在几秒钟内重复。

我用perf进行了一些分析,发现IPC与减速的比例下降了。在Haswell系统中,这似乎是由更多错过的分支引起的,但为什么预测率会下降? Radiance确实使用随机数生成器 - 可能“更好”的随机性导致错过的分支?但除了OMAP4支持外,RNG在3.12中似乎没有变化。

在AMD系统上,perf只指向更多空闲的后端周期,但原因尚不清楚。

Haswell系统:

3.11.10  895s user, 3.74% branch-misses, 1.65 insns per cycle
3.12.6   962s user, 4.22% branch-misses, 1.52 insns per cycle

Richland系统:

3.11.10  1764s user, 8.23% branch-misses, 0.75 insns per cycle
3.12.6   1844s user, 8.26% branch-misses, 0.72 insns per cycle

我还查看了两个内核的dmesg输出中的差异,但没有看到任何可能导致CPU绑定程序如此减速的内容。

我尝试将cpufreq调控器从默认的 ondemand 切换到 peformance ,但这没有任何效果。

可执行文件是使用gcc 4.7.3编译的,但不使用AVX指令。 libm似乎仍然使用一些AVX(例如__ieee754_pow_fma4),但这些功能仅占总执行时间的0.3%。

其他信息:

任何想法(除了平分内核更改)?

2 个答案:

答案 0 :(得分:7)

让我们检查您的perf stat输出:http://www.chr-breitkopf.de/tmp/perf-stat.A8.txt

内核3.11.10

    1805057.522096 task-clock                #    0.999 CPUs utilized          
           183,822 context-switches          #    0.102 K/sec                  
               109 cpu-migrations            #    0.000 K/sec                  
            40,451 page-faults               #    0.022 K/sec                  
 7,523,630,814,458 cycles                    #    4.168 GHz                     [83.31%]
   628,027,409,355 stalled-cycles-frontend   #    8.35% frontend cycles idle    [83.34%]
 2,688,621,128,444 stalled-cycles-backend    #   35.74% backend  cycles idle    [33.35%]
 5,607,337,995,118 instructions              #    0.75  insns per cycle        
                                             #    0.48  stalled cycles per insn [50.01%]
   825,679,208,404 branches                  #  457.425 M/sec                   [66.67%]
    67,984,693,354 branch-misses             #    8.23% of all branches         [83.33%]

    1806.804220050 seconds time elapsed

内核3.12.6

    1875709.455321 task-clock                #    0.999 CPUs utilized          
           192,425 context-switches          #    0.103 K/sec                  
               133 cpu-migrations            #    0.000 K/sec                  
            40,356 page-faults               #    0.022 K/sec                  
 7,822,017,368,073 cycles                    #    4.170 GHz                     [83.31%]
   634,535,174,769 stalled-cycles-frontend   #    8.11% frontend cycles idle    [83.34%]
 2,949,638,742,734 stalled-cycles-backend    #   37.71% backend  cycles idle    [33.35%]
 5,607,926,276,713 instructions              #    0.72  insns per cycle        
                                             #    0.53  stalled cycles per insn [50.01%]
   825,760,510,232 branches                  #  440.239 M/sec                   [66.67%]
    68,205,868,246 branch-misses             #    8.26% of all branches         [83.33%]

    1877.263511002 seconds time elapsed

在“周期”字段中,3.12.6有近300个Gcycles;只有6,5辆Gcycles是前端的摊位,261辆Gcycles在后端停滞不前。你只有0.2G的额外分支未命中(每个成本大约20个周期 - 每个optim.manual第597页;所以4Gcycles),所以我认为你的性能问题与内存子系统问题有关(更现实的后端事件,它可以受内核的影响)。 Pagefaults差异和迁移计数很低,我认为它们不会直接减慢测试速度(但是迁移可能会将程序移到更糟糕的位置)。

你应该深入perf计数器来找到确切的问题类型(如果你有更短的测试运行会更容易)。英特尔手册http://www.intel.com/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-optimization-manual.pdf将为您提供帮助。检查第587页(B.3.2)了解整体事件层次结构(FE和BE停顿也在这里),B.3.2.1-B.3.2.3检查后端停顿信息以及如何开始挖掘(检查缓存事件等) )及以下。

内核如何影响内存子系统?它可以设置不同的虚拟到物理映射(几乎不是您的情况),也可以将进程远离数据。你没有NUMA机器,但Haswell不是确切的UMA - 有一个环形总线,一些内核更靠近内存控制器或共享LLC的某些部分(最后一级缓存)。您可以使用taskset实用程序测试程序,将其绑定到某个核心 - 内核不会将其移动到其他核心。

更新:在检查A8的新性能数据后,我们发现3.12.6有更多DLTB未命中。随着/ proc / pid / maps中的更改(很多简短的[heap]部分而不是单个[heap],仍然没有确切的信息),我认为透明的巨页(THP; 2M)可能存在差异对于相同数量的内存和较少的tlb未命中所需的TLB条目较少,例如在3.12中,由于短堆部分而无法应用它。

您可以查看/proc/PID/smaps AnonHugePages/proc/vmstat的thp *值,以查看结果。这些值记录在kernel.org/doc/Documentation/vm/transhuge.txt

  

@osgx你找到了原因!在echo之后永远不会> / sys / kernel / mm / transparent_hugepage / enabled,3.11.10需要3.12.6!

好消息!

  

有关如何禁用随机化的其他信息,以及将此报告为错误的位置(7%性能回归非常严重)将不胜感激

我错了,这个多堆部分效果不是brk随机化(它只改变了堆的开头)。这是do_brk中VMA合并的失败;不知道为什么,但在mm 3.11.10 - 3.12.6之间看到了VM_SOFTDIRTY的一些变化。

UPDATE2:未合并VMA的可能原因:

3.11中

http://lxr.missinglinkelectronics.com/linux+v3.11/mm/mmap.c#L2580 do_brk

3.12中

http://lxr.missinglinkelectronics.com/linux+v3.11/mm/mmap.c#L2577 do_brk

3.12刚刚在do_brk

的末尾添加
2663        vma->vm_flags |= VM_SOFTDIRTY;
2664        return addr;

我们有点

2635        /* Can we just expand an old private anonymous mapping? */
2636        vma = vma_merge(mm, prev, addr, addr + len, flags,
2637                                        NULL, NULL, pgoff, NULL);

vma_merge内部有vm_flags测试

http://lxr.missinglinkelectronics.com/linux+v3.11/mm/mmap.c#L994 3.11

http://lxr.missinglinkelectronics.com/linux+v3.12/mm/mmap.c#L994 3.12

1004        /*
1005         * We later require that vma->vm_flags == vm_flags,
1006         * so this tests vma->vm_flags & VM_SPECIAL, too.
1007         */

vma_merge - > can_vma_merge_before - > is_mergeable_vma ...

 898        if (vma->vm_flags ^ vm_flags)
 899                return 0;

但在检查时,新的vma未标记为VM_SOFTDIRTY,而旧标记已标记为。

答案 1 :(得分:0)

此更改可能是候选人http://marc.info/?l=linux-kernel&m=138012715018064。我松散地说,因为我没有资源确认。值得注意的是,这是3.11.10和3.12.6之间调度程序唯一的重要更改。

无论如何,我很有兴趣看到你的调查结果,所以请随时发布。