OpenMP vs gcc编译器优化

时间:2015-12-16 22:33:46

标签: c gcc openmp

我正在学习openmp,使用通过quadature计算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;
}

我将这与使用并行减少的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编译器优化,运行时间约为4s(串行)和.66s(omp)。使用-O3标志,串行运行时将降至“.000001s”,并且omp运行时基本不变。这里发生了什么?是使用矢量指令,还是代码或定时方法不好?如果它是矢量化,为什么omp函数不会受益?

我正在使用的机器正在使用现代的6核Xeon处理器。

谢谢!

1 个答案:

答案 0 :(得分:3)

编译器超出你的要求。对于串行版本,它能够检测到从未使用过计算结果。因此它完全抛弃了计算。

double start_time = omp_get_wtime();
serial(); //<-- Computations not used.
double end_time = omp_get_wtime();

在openMP的情况下,编译器无法看到函数体内是否真的没有效果,所以为了保持安全,它会保持函数调用。

你当然可以写一些像double serial_pi = serial();这样的东西,并且在时间测量之外用变量serial_pi做一些虚拟的东西。这样编译器将保持函数调用并执行您实际需要的优化。