首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

评估 Linux on POWER 的性能(6)

评估 Linux on POWER 的性能(6)

清单 20. GET_HIGH_WORD 宏定义
1
2
3
4
5
6
#define GET_HIGH_WORD(i,d)                                      \
do {                                                            \
  ieee_double_shape_type gh_u;                                  \
  gh_u.value = (d);                                             \
  (i) = gh_u.parts.msw;                                         \
} while (0)




在这个宏中,造成 LHS 停滞的罪魁祸首可能是将 float 的属性读取到了内部 value,然后将它读取到变量 i 的操作。POWER7 处理器没有将浮点寄存器的内容逐位转移到定点寄存器的原生指令。在 POWER 上实现该操作的方式是,使用一个存储操作将浮点寄存器中的 FP 数字存储到内存,然后将相同的内存位置加载到一个定点寄存器(通用)。由于内存访问比寄存器操作慢(即使在访问 L1 数据缓存时也如此),在存储过程中,CPU 会停滞,以便完成后续的加载。
:文档 "POWER ISA 2.06 (POWER7)"包含更多的信息。
最常见的性能计数器事件触发中断,保留一个与执行指令接近的指令 PC 地址。这可能会导致不完全准确的程序集注释。为了缓解这种行为 POWER4,并在以后有一组有限的名称为 marked 的性能计数器。标记的指令在每个时间框架内将产生较少的事件;然而,PC 指令会是准确的,导致准确的程序集注释。标记的事件在 opcontrol -l 获得的 OProfile 计数器列表中带有 PM_MRK 前缀。
仔细检查分析,查看 PM_MRK_LSU_REJECT_LHS 计数器。PM_MRK_LSU_REJECT_LHSPM_LSU_REJECT_LHS 这两个计数器监视相同的性能事件。不过,标记的计数器 (PM_MRK_LSU_REJECT_LHS) 在每个时间框架内会产生较少的事件,但带有更准确的程序集注释。
清单 21. PM_MRK_LSU_REJECT_LHS POWER7 事件的 perf record
1
2
3
4
5
$ perf record -C 0 -e rd082 taskset -c 0 ./hypot_bench_glibc
$ perf report
Events: 256K raw 0xd082
    64.61%  hypot_bench_gli  libm-2.12.so       [.] __ieee754_hypot
    35.33%  hypot_bench_gli  libm-2.12.so       [.] __GI___finite




这会生成 中的程序集注释。
清单 22. PM_MRK_LSU_REJECT_LHS POWER7 事件的 perf report
1
2
3
4
5
6
7
8
9
10
11
         :        00000080fc38b730 <.__ieee754_hypot>:
[...]
    1.23 :          80fc38b7a8:   c9 a1 00 70     lfd     f13,112(r1)
    0.00 :          80fc38b7ac:   f8 01 00 70     std     r0,112(r1)
   32.66 :          80fc38b7b0:   c8 01 00 70     lfd     f0,112(r1)
[...]
    0.00 :          80fc38b954:   f8 01 00 70     std     r0,112(r1)
    0.00 :          80fc38b958:   e8 0b 00 00     ld      r0,0(r11)
    0.00 :          80fc38b95c:   79 00 00 0e     rldimi  r0,r8,32,0
   61.72 :          80fc38b960:   c9 61 00 70     lfd     f11,112(r1
[...]




另一个符号显示大约有 35% 的生成事件有类似的行为,如
清单 23. perf report 的更多重点
1
2
3
       :        00000080fc3a2610 <.__finitel>>
  0.00 :          80fc3a2610:   d8 21 ff f0     stfd    f1,-16(r1)
100.00 :          80fc3a2614:   e8 01 ff f0     ld      r0,-16(r1)




根据这些信息,优化工作可能是,通过删除 FP 到 INT 的转换,消除这些停滞。POWER 处理器具有快速、高效的 Float-Point 执行单元,所以不需要使用 Fixed-Point 指令来执行这些计算。POWER 目前在 GLIBC 中使用的算法 (sysdeps/powerpc/fpu/e_hypot.c) 只使用 FP 操作就可以删除所有 LHS 停滞。结果是获得了更简单的算法,如  所示。
清单 24. PowerPC GLIBC hypot 源代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
double
__ieee754_hypot (double x, double y)
{
  x = fabs (x);
  y = fabs (y);

  TEST_INF_NAN (x, y);

  if (y > x)
    {
      double t = x;
      x = y;
      y = t;
    }
  if (y == 0.0 || (x / y) > two60)
    {
      return x + y;
    }
  if (x > two500)
    {
      x *= twoM600;
      y *= twoM600;
      return __ieee754_sqrt (x * x + y * y) / twoM600;
    }
  if (y < twoM500)
    {
      if (y <= pdnum)
        {
          x *= two1022;
          y *= two1022;
          return __ieee754_sqrt (x * x + y * y) / two1022;
        }
      else
        {
          x *= two600;
          y *= two600;
          return __ieee754_sqrt (x * x + y * y) / two600;
        }
    }
  return __ieee754_sqrt (x * x + y * y);
}




TEST_INF_NAN 宏是更进一步的小优化,在开始更进一步的 FP 操作之前,它会测试某个数是 NaN 还是 INFINITY(这是由于针对 NaN 和 INFINITY 的操作可能会增加 FP 异常,而函数规范不允许这一点)。在 POWER7 上,isinf 和 isnan 函数调用被编译器优化为 FP 指令,并且不会产生额外的函数调用,而在较旧的处理器(POWER6 和更旧的版本)上,它将对各函数分别生成一个调用。优化基本上是相同的实现,但是内联的,以避免函数调用。
最后,比较这两种实现,执行下面的简单测试。在使用和不使用新算法的情况下重新编译 GLIBC,比较每个基准运行的总时间。默认 GLIBC 实现结果位于 中:
1
2
3
4
5
6
7
8
9
$ /usr/bin/time ./hypot_bench_glibc
INF_CASE       : elapsed time: 14:994339
NAN_CASE       : elapsed time: 14:707085
TWO60_CASE     : elapsed time: 12:983906
TWO500_CASE    : elapsed time: 10:589746
TWOM500_CASE   : elapsed time: 11:215079
NORMAL_CASE    : elapsed time: 15:325237
79.80user 0.01system 1:19.81elapsed 99%CPU (0avgtext+0avgdata 151552maxresident)k
0inputs+0outputs (0major+48minor)pagefaults 0swaps




优化版本的结果如 中所示:
清单 26. Benchmark with optimized GLIBC hypot
1
2
3
4
5
6
7
8
9
$ /usr/bin/time ./hypot_bench_glibc
INF_CASE       : elapsed time: 4:667043
NAN_CASE       : elapsed time: 5:100940
TWO60_CASE     : elapsed time: 6:245313
TWO500_CASE    : elapsed time: 4:838627
TWOM500_CASE   : elapsed time: 8:946053
NORMAL_CASE    : elapsed time: 6:245218
36.03user 0.00system 0:36.04elapsed 99%CPU (0avgtext+0avgdata 163840maxresident)k
0inputs+0outputs (0major+50minor)pagefaults 0swaps




这最终将获得超过 100% 的性能提高,使基准时间减少一半。
返回列表