OpenMP与gcc编译器优化对比

6

我正在学习使用openmp通过积分计算pi的例子。在串行中,我运行以下C代码:

double serial() {
    double step;
    double x,pi,sum = 0.0;

    step = 1.0 / (double) num_steps;

    for (int i = 0; i < num_steps; i++) {
        x = (i + 0.5) * step; // forward quadature
        sum += 4.0 / (1.0 + x*x);
    }
    pi = step * sum;

    return pi;
}

我正在将这个与使用并行for和reduction的omp实现进行比较:

double SPMD_for_reduction() {
    double step;
    double pi,sum = 0.0;

    step = 1.0 / (double) num_steps;

    #pragma omp parallel for reduction (+:sum)
    for (int i = 0; i < num_steps; i++) {
        double x = (i + 0.5) * step;
        sum += 4.0 / (1.0 + x*x);
    }
    pi = step * sum;

    return pi;
}

当num_steps = 1,000,000,000,omp情况下使用6个线程,我进行编译并计时:

    double start_time = omp_get_wtime();
    serial();
    double end_time = omp_get_wtime();

    start_time = omp_get_wtime();
    SPMD_for_reduction();
    end_time = omp_get_wtime();

不使用任何cc编译器优化的情况下,串行运行时间约为4秒,而omp的运行时间为0.66秒。如果使用-O3标志,串行运行时会降至“0.000001秒”,而omp运行时间几乎不变。这是怎么回事?是在使用矢量指令,还是代码或计时方法很差?如果是矢量化,为什么omp函数没有受益呢?

值得注意的是,我使用的机器是一台现代的6核Xeon处理器。

谢谢!


10
https://en.wikipedia.org/wiki/Dead_code_elimination - Mysticial
1个回答

4
编译器比你聪明。对于串行版本,它能够检测到你的计算结果从未被使用。因此,它完全舍弃了计算。
double start_time = omp_get_wtime();
serial(); //<-- Computations not used.
double end_time = omp_get_wtime();

在openMP情况下,编译器无法确定函数体内的所有内容是否没有影响,所以为了保险起见,它会保留函数调用。你当然可以像这样写:double serial_pi = serial();,在时间测量之外对变量serial_pi进行一些虚假操作。这样编译器将保留函数调用并执行您实际寻找的优化。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接