我试图通过并行化矩阵乘法来提高相当复杂的迭代算法的性能,矩阵乘法在每次迭代时被调用。 该算法需要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秒。 而我不明白的是小并行部分如何影响算法的其余部分?
答案 0 :(得分:2)
对于10次迭代和一个简单的赋值,我想与计算本身相比,OpenMP开销太多了。这里看起来很轻巧的实际上是管理和同步多个线程,这些线程甚至可能来自线程池。可能存在一些锁定,我不知道MSVC在估计是否要并行化方面有多好。
尝试使用更大的循环体或更大量的迭代(例如1024 * 1024次迭代,仅适用于初学者)。
示例OpenMP Magick:
#pragma omp parallel for private(j)
for (int i = 0; i < 10; i++)
j = i;
这可能是大致由编译器扩展到:
const unsigned __cpu_count = __get_cpu_count();
const unsigned __j = alloca (sizeof (unsigned) * __cpu_count);
__thread *__threads = alloca (sizeof (__thread) * __cpu_count);
for (unsigned u=0; u!=__cpu_count; ++u) {
__init_thread (__threads+u);
__run_thread ([u]{for (int i=u; i<10; i+=__cpu_count)
__j[u] = __i;}); // assume lambdas
}
for (unsigned u=0; u!=__cpu_count; ++u)
__join (__threads+u);
__init_thread()
,__run_thread()
和__join()
是调用某些系统调用的非平凡函数。
如果使用线程池,您可以用alloca()
左右替换第一个__pick_from_pool()
。
(请注意,名称和发出的代码,都是虚构的,实际实现看起来会有所不同)
关于您更新的问题:
您似乎以错误的粒度进行并行化。在线程中放置尽可能多的工作量,而不是
for (...) {
#omp parallel ...
for (...) {}
}
试
#omp parallel ...
for (...) {
for (...) {}
}
经验法则:每个线程保持足够大的工作负载,以减少相对开销。
答案 1 :(得分:0)
也许只是j = i对于core-cpu bandwith来说并不是高收益。也许你应该尝试更多的计算方法。 (用于实现i * i * i * i * i * i并将其除以i + i + i)
你在多核cpu或gpu上运行吗?