c优化2行关键代码

使用valgrind和perf / FlameGraphs,我已经确定了部分应用程序占用了几乎100%的CPU:

for(size_t i = 0; i < objects.size(); i++) {

  //this part consumes 11% CPU -----> 
  collions_count = database->get_collisions(collisions_block, objects[i].getKey());
  feature1 = objects[i].feature1;
  //<--------

  for(int j = 0; j < collions_count * 2; j += 2) {

    hash = 
      ((collisions_block[j] & config::MASK_1) << config::SHIFT) | 
      ((collisions_block[j+1] - feature1) & config::MASK_2);

    if (++offsets[hash] >= config::THRESHOLD_1) {

      //... this part consumes < 1% of CPU

    }
  }
}

hash和follow if语句的计算占用了所有应用程序的近90%的CPU.

> collisions_block初始化一次,类型为int [100000]
> config ::是一个包含全局配置变量的命名空间
>偏移初始化一次,类型为uint8_t [1 << 24]
>我正在运行Centos7 Linux 3.10.0-327.13.1.el7.x86_64
>所有CPU都用于usr,mpstat输出中没有iowait
>我正在编译g(GCC)4.8.5 20150623(Red Hat 4.8.5-4)和标志-std = gnu 11 -Ofast -Wall

有没有办法加快内循环?

最佳答案 我发现性能瓶颈是对数组偏移[hash]的无序访问.耗费了大部分CPU时间(75%).通过将阵列的尺寸从1 <24小时减小到1 <21并且尝试适当的MASKS配置,我实现了2.5倍的速度增加. 我将简要介绍一下如何确定问题

for(size_t i = 0; i < objects.size(); i++) {

  //this part consumes 11% CPU -----> 
  collions_count = database->get_collisions(collisions_block, objects[i].getKey());
  feature1 = objects[i].feature1;
  //<--------

  for(int j = 0; j < collions_count * 2; j += 2) {

    hash = calculate_hash(collisions_block[j], 
      collisions_block[j+1],
      feature1,
      config::MASK_1,
      config::MASK_2
      config::SHIFT);

    if (check_condition(hash, config::THRESHOLD_1)) {

       //... this part consumes < 1% of CPU

    }
  }
}

>将关键的2行拆分为单独的函数以便更好地进行分析(小心放置__attribute __((noinline))以防止gcc内联新函数.如果内联,它们不会出现在调用堆栈中)
>使用-g -rdynamic gcc标志编译代码
>运行采样pefrormance工具perf记录-p< pid> -F 200 -g – 呼叫图矮人 – 睡60
>转换为FlameGraph以获得更好的可读性性能脚本| ./stackcollapse-perf.pl\u0026gt; out.perf-fold&& ./flamegraph.pl out.perf-folded> graph.svg
>从火焰图中识别最昂贵的功能并对其进行优化

点赞