中文
注册
我要评分
文档获取效率
文档正确性
内容完整性
文档易理解
在线提单
论坛求助

串行代码导致执行时间过长

现象

应用编码时,串行代码可能存在以下问题:

  • 由于A函数执行过长导致B函数调用被阻塞,应用执行效率降低,执行时间变长。
  • 循环体内对函数调用时易产生串行调用逻辑,单次调用结束后才进行下一次调用,导致循环体执行时间过长,使应用整体执行效率降低。

调优思路

通过鲲鹏DevKit系统性能分析的HPC应用分析定位耗时较长的函数,对源码进一步分析,将不存在依赖关系的A、B函数进行并行调用,或在循环体内并行调用多个函数,提高执行效率,缩短应用运行时间。

操作步骤

  1. 准备示例源码serial_time.c并进行编译。
    gcc serial_time.c -O3 -o serial_time -fopenmp -lm
  2. 使用鲲鹏DevKit系统性能分析执行HPC应用分析任务。
    表1 任务配置参数说明

    参数

    说明

    分析对象

    应用

    应用路径

    输入程序所在的绝对路径,例如本示例将代码样例放在服务器“/opt/testdemo/serial_time”路径下。

    分析类型

    HPC应用分析

    采集模式

    OpenMP模式;本示例主要是对OMP的应用进行分析。

    分析模式

    统计分析

    采样模式

    Detail模式

    采样时长

    默认

  3. 查看任务结果。
    分析后观察执行时间,发现串行代码执行时间占比99.89%,严重影响整个应用的执行效率。
    图1 应用执行时间
  4. 源码分析。

    main函数占比最高,进一步分析源码,源码内main中关键函数SericalTimeBench使用了串行执行。

    图2 Hotspots
    void SericalTimeBench(Point *pointA, Point *pointB, double *pointDis, int n)
    {
        assert(pointA != NULL && pointB != NULL && pointDis != NULL);
        int i;
        for (i = 0; i < n; i++) {
            pointDis[i] = ComputPointDistance(&pointA[i], &pointB[i]);
        }
    }
  5. 使用OpenMP并行调用耗时的计算代码。
    void SericalTimeBench_OPT(Point *pointA, Point *pointB, double *pointDis, int n)
    {
        assert(pointA != NULL && pointB != NULL && pointDis != NULL);
        int i;
        #pragma omp parallel for shared (n) private (i)
        for (i = 0; i < n; i++) {
            pointDis[i] = ComputPointDistance(&pointA[i], &pointB[i]);
        }
    }
  6. 重新编译后分析。

    使用1中的命令重新编译应用并运行,观察运行时间。

优化效果

优化后重新编译应用并运行,应用执行耗时由优化前的299秒变为27秒左右,时间大幅缩短。

图3 优化后分析结果