梯形法则在C语言中实现的性能改进

euoag5mw  于 2023-03-22  发布在  其他
关注(0)|答案(1)|浏览(99)

我试图提高我的积分算法的性能(速度)。它是使用扩展梯形法则在C中实现的。一个例子,其中要积分的函数是x * exp(-x)从0.1到1000,是:

double x, integral = 0; // initialize
    int N = 10000;          // number of points to use
    double h = 0.1;         // step size
    int X = 1000;           // end of integration domain
    for (int k = 2; k < N; k++)
    {
        x = k * h;
        integral += x * exp(-x);
    }
    // deal with end points
    x = h;
    integral += 0.5 * x * exp(-x);
    x = X;
    integral += 0.5 * x * exp(-x);
    integral = h * integral;

理想情况下,我希望通过将代码矢量化或并行化来使用更多的CPU。但是,我无法让Windows上的Microsoft编译器自动完成此操作(我正在使用cl /O2 /fp:fast /Qpar进行编译)。
任何关于提高性能的提示都非常感谢。
编辑:我想知道Matlab是如何做到这一点的。如果你在Matlab中的一个数组上使用trapz,那么所有的核心都是活动的。

nfzehxib

nfzehxib1#

您可以add /Qpar-report:2 option使编译器输出并行化失败的原因。
使用/O2 /Qpar /Qpar-report:2编译代码会导致消息loop not parallelized due to reason '1008'。此原因代码可以在Vectorizer and parallelizer messages页面上查找。代码1004表示循环未并行化,因为它包含标量减少。
您仍然可以并行计算x * exp(-x),如下所示:

#include <math.h>

double integrate() {
    double x, integral = 0;  // initialize
    constexpr int N = 10000; // number of points to use
    double h = 0.1;          // step size
    int X = 1000;            // end of integration domain

    double f[N];

    #pragma loop(hint_parallel(0))
    for (int k = 2; k < N; k++) {
        double x = k * h;
        f[k] = x * exp(-x);
    }

    for (int k = 2; k < N; k++) {
        integral += f[k];
    }
    // deal with end points
    x = h;
    integral += 0.5 * x * exp(-x);
    x = X;
    integral += 0.5 * x * exp(-x);
    integral = h * integral;
    return integral;
}

需要#pragma loop(hint_parallel(0))来强制循环的并行化,否则它拒绝并行化,原因是1008(“编译器检测到这个循环没有做足够的工作来证明自动并行化。
请注意,代码必须使用C++编译器编译,因为msvc C编译器不支持constexpr

相关问题