【发布时间】:2012-07-13 19:51:53
【问题描述】:
我试图通过并行化矩阵乘法来提高相当复杂的迭代算法的性能,每次迭代都会调用该矩阵乘法。 该算法需要 500 次迭代和大约 10 秒。但是在并行化矩阵乘法之后,它会减慢到 13 秒。 但是,当我单独测试相同维度的矩阵乘法时,速度有所提高。 (我说的是 100x100 矩阵。)
最后,我关闭了算法内部的任何并行化,并在每次迭代中添加了以下代码,它完全没有任何作用,而且大概不会花费很长时间:
int j;
#pragma omp parallel for private(j)
for (int i = 0; i < 10; i++)
j = i;
同样,与没有这段代码的相同算法相比,速度会降低 30%。
因此,在主算法中使用 openmp 调用任何并行化 500 次会以某种方式减慢速度。这种行为对我来说看起来很奇怪,有人知道问题是什么吗?
主要算法被桌面应用程序调用,由VS2010,Win32 Release编译。 我在 Intel Core i3(并行化创建 4 个线程)、64 位 Windows 7 上工作。
这是一个程序的结构:
int internal_method(..)
{
...//no openmp here
// the following code does nothing, has nothing to do with the rest of the program and shouldn't take long,
// but somehow adding of this code caused a 3 sec slowdown of the Huge_algorithm()
double sum;
#pragma omp parallel for private(sum)
for (int i = 0; i < 10; i++)
sum = i*i*i / (1.0 + i*i*i*i);
...//no openmp here
}
int Huge_algorithm(..)
{
...//no openmp here
for (int i = 0; i < 500; i++)
{
.....// no openmp
internal_method(..);
......//no openmp
}
...//no openmp here
}
所以,最后一点是: 单独调用并行代码 500 次(当算法的其余部分被省略时)需要不到 0.01 秒,但是当你在一个巨大的算法中调用它 500 次时,它会导致整个算法延迟 3 秒。 而我不明白的是小的并行部分如何影响算法的其余部分?
【问题讨论】:
-
只是为了确定,您如何衡量执行时间?我在 SO 上看到了很多与 OpenMP 和 MT 相关的问题,人们在并行程序中测量 CPU 时间而不是挂钟时间。另一件事是:进入和退出并行区域相对昂贵(即使使用现代池化 OMP 运行时)。
-
我使用的是挂钟时间,桌面应用程序实际测量时间。进入和退出平行区域确实如此,但我有 500 次进入和退出,并且减速了 3 秒 - 这并不累加。
-
500 个并行区域的 3 秒平均每个并行区域的开销为 6 毫秒,包括开始时的线程唤醒和结束时的同步等待。不幸的是,我无法找到有关从 Win32 线程池唤醒线程需要多长时间的信息,但 6 毫秒接近大多数 x86/x64 操作系统的调度间隔。只要时间允许,我应该做一些测量。
-
@Hristo Iliev:非常好的评论:)
标签: c++ visual-studio-2010 openmp