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);
}
但是在测试中并行解决方案比后续解决方案慢
- 秒:0 毫秒
- 并行: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 个内核,就没有必要。
我用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);
}
但是在测试中并行解决方案比后续解决方案慢
- 秒:0 毫秒
- 并行: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 个内核,就没有必要。