在Visual Studio 2013中OpenMP的性能下降

Performance decrease in OpenMP with Visual Studio 2013

本文关键字:性能 OpenMP Visual Studio 2013      更新时间:2023-10-16

我用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);
}

但在测试中并行解决方案比顺序解决方案慢,时间为

  • parallel: 25毫秒!!!!

为什么会这样?

我使用的是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核,它就不应该是必要的。