c++ 计算相同函数时,线程在并行区域中的运行速度比在临界区域中的运行速度慢

9jyewag0  于 2022-11-19  发布在  其他
关注(0)|答案(2)|浏览(179)

我有一个函数void dynamics (A a, std::vector<double> &, std::vector<double> &, std::vector<double> ),我从openmp创建的线程中调用它。该函数的输入是每个线程(在并行块中创建)的私有输入。

#include <iostream>
#include <vector>
#include <chrono>
using namespace std;

class A {
 some code
};

int main(void)
{
vector<double> a (12,0.0);
vector<double> b (12,0.0);

#pragma omp parallel for shared(a,b)
for(int id = 0; id < 6; id++) {

vector<double> a_private (2,0.0);
vector<double> b_private (2,0.0);
vector<double> c_private (2,(double)id);
A d;

start_time for each thread - chrono
dynamics(d,a_private,b_private,c_private);
end_time for each thread - chrono
calculate_time for each thread

# pragma omp critical
{
for(int i = 0; i < 2; i++) a[i+(2*id)] = a_private[i];
for(int i = 0; i < 2; i++) b[i+(2*id)] = b_private[i];
}

}

print(a);
print(b);

return 0;

}

这里,为了避免争用条件,我已经将a_private和B_private的赋值放到临界区内的a和b中。
当我为每个线程计算上述代码的时间时,它比我将动态函数放在临界区中的时间要多。

# pragma omp critical
{
start_time for each thread - chrono
dynamics(d,a_private,b_private,c_private);
end_time for each thread - chrono
calculate_time for each thread
for(int i = 0; i < 2; i++) a[i+(2*id)] = a_private[i];
for(int i = 0; i < 2; i++) b[i+(2*id)] = b_private[i];
}

最后的输出(a和B)在这两种情况下是相同的(多次运行代码给予相同的结果)。因此,我相信动态是线程安全的(难道它不是线程安全的吗?)
动态的输入是在并行区域中创建的,因此,它们应该是每个线程的私有的(是吗?)。
为什么线程在一起工作时计算动态的速度比一个接一个工作时(在临界段内)慢?
我相信创建和管理线程的开销不会是一个问题,因为我比较了总是创建线程的时间(在我的上述两种情况下)。
并行化动态后的总时间低于串行版本(实现了加速),但为什么线程所用时间会有显著差异(在临界范围内,而不是:计算线程时间)。
我能想到的解释是,运行动态会产生竞态条件,即使它的输入和输出对每个线程都是私有的。(会是这样吗?)
此外,我没有使用omp get num threads和omp get thread num。
这里有什么问题?

When running dynamics in parallel
ID = 3, Dynamics Time = 410233
ID = 2, Dynamics Time = 447835
ID = 5, Dynamics Time = 532967
ID = 1, Dynamics Time = 545017
ID = 4, Dynamics Time = 576783
ID = 0, Dynamics Time = 624855

When running dynamics in critical section
ID = 0, Dynamics Time = 331579
ID = 2, Dynamics Time = 303294
ID = 5, Dynamics Time = 307622
ID = 1, Dynamics Time = 340489
ID = 3, Dynamics Time = 303066
ID = 4, Dynamics Time = 293090

(将不能提供最小的动力学再现,因为它是我的教授的专有)

  • 谢谢-谢谢
tnkciper

tnkciper1#

这是一个典型的/常见的情况,其中加速与线程数不成比例。有几种解释:
1.当单个线程单独运行时(即只有一个内核100%负载),CPU频率会提高(加速),而当多个线程并发运行时,CPU仅保持标称频率

  1. dynamics()内部的代码是(接近)内存受限的。也就是说,当多个线程并发运行时,CPU和RAM之间的带宽往往会饱和,内核无法接收到足够的数据来100%地运行
qpgpyjmq

qpgpyjmq2#

我测量了向量操作的计算时间,与您在单线程和多线程上的代码几乎相似。此外,在每个测试中使用了两种不同的向量大小。当向量数为1000时,并行速度稍慢,但当n=1000000时,并行速度比串行速度慢。正如我们将看到的,进程处理的数据量更大。CPU和存储器之间的数据通信量更大,从而导致并行性能降低。

num vector = 10000
Parallel
id=0091152 time=10155
id=0082408 time=10169
id=0074644 time=10172
id=0135644 time=10269
id=0092996 time=10303
id=0133796 time=10348
id=0135884 time=10420

Serial
id=0132880 time=7635
id=0106048 time=7643
id=0072972 time=7618
id=0107080 time=7794
id=0100064 time=7942
id=0110648 time=8044
id=0111988 time=7849

---------------------

num vector = 1000000
Parallel
id=0069820 time=27000
id=0135668 time=27106
id=0118184 time=27144
id=0102572 time=27158
id=0046388 time=27165
id=0120604 time=27173
id=0044344 time=27188

Serial
id=0038320 time=5341
id=0133000 time=5253
id=0101508 time=5168
id=0004840 time=5212
id=0087408 time=5143
id=0130548 time=5199
id=0122764 time=5126

time unit=msec

相关问题