Visual Studio 2013 年 OpenMP 的性能下降

Performance decrease in OpenMP with Visual Studio 2013

我用VisualStudio 2013编写了一个openmp的基本例子,这个例子是曲线下面积的计算。这是安全实现

int integral(int a, int b, int n_intervalos, int(*function)(int))
{
    int long_interv = (b - a) / n_intervalos;
    int suma = 0;
    for (int i = a; i < b; i+=long_interv)
    {
        int h = function(i);
        suma += h * long_interv;
    }
    return suma;
}

当我去测试这段代码时,我使用了这个数据集

int intg = integral(0, 120, 120, funcion);

我想使用 OpenMP 来提高性能然后我做了以下功能

void integralParalelo(int a, int b, int n_intervalos, int(*function)(int), int *area)
{
    int max_threads = omp_get_max_threads();
    int thread_id = omp_get_thread_num();
    int sub_intervalo = n_intervalos / max_threads;

    int long_interv = (a + b) / n_intervalos;
    int ini = thread_id * long_interv * sub_intervalo;
    int fin = sub_intervalo * long_interv + ini;
    int suma = integral(ini, fin, sub_intervalo, function);

    #pragma omp critical
    {
        (*area) = (*area) + suma;
    }
}

而我是这样调用这个函数的

#pragma omp parallel num_threads(4)
{
    integralParalelo(0, 120, 120, funcion, &area);
}

但是在测试中并行解决方案比后续解决方案慢

为什么会这样?

我正在使用 Visual Studio Ultimate 2013,我的电脑是 AMD A10-5745M

这里可能发生了两件事。

首先是您在不必要时将 OpenMP 当作 MPI。在您的情况下,您真正​​应该做的就是并行化您的 for 循环并记住对 suma 变量执行缩减。您自己调用 OpenMP 例程并拆分域的方式在我看来更像是 MPI 代码。

其次,您处理的数据集太小。您真正需要做的是在串行代码需要 60 多秒时测试它,然后将时间与具有 4 个处理器的 OpenMP 运行 进行比较。请记住,创建线程组需要时间,如果每个线程只做很少的工作,那么您的大部分时间将花在启动上。

因为你在 for 循环中做的实际工作很少,我怀疑你不会获得超过 2-3 倍的 4 核性能。

我建议这样做:

int integralParallel(int a, int b, int n_intervalos, int(*function)(int))
{
    int long_interv = (b - a) / n_intervalos;
    int suma = 0;
    #pragma omp parallel for default(shared) reduction(+:suma)
    for (int i = a; i < b; i+=long_interv)
    {
        int h = function(i);
        suma += h * long_interv;
    }
    return suma;
}

并像调用串行代码一样调用它。如果需要,请指定 num_threads(4),但只要 OpenMP 正在获取您的 4 个内核,就没有必要。