我正在运行一段代码来测试log()函数是否在scale中。我在4核机器上运行它,结果显示它没有扩展。我的代码如下:
#include<iostream>
#include<cmath>
#include<omp.h>
#include<chrono>
using namespace std;
typedef std::chrono::milliseconds ms;
int main(){
#pragma omp parallel for schedule(static)
for(int i=0;i<4;i++){
auto start = std::chrono::high_resolution_clock::now();
double tmp=1.0;
for(double j=0.0;j<10000000;j++){
tmp=log(j);
}
auto end = std::chrono::high_resolution_clock::now();
#pragma omp critical
{
cout<<"tmp="<<tmp<<endl;
cout<<"Thread "<<omp_get_thread_num()<<" calculated tmp, time used: "<<std::chrono::duration_cast<ms>(end - start).count() << "ms" << endl;
}
}
return 0;
}
如果我使用4个线程,结果是:
Thread 1 calculated tmp, time used: 21ms
Thread 0 calculated tmp, time used: 21ms
Thread 2 calculated tmp, time used: 21ms
Thread 3 calculated tmp, time used: 21ms
如果仅使用1个线程,则结果为:
Thread 0 calculated tmp, time used: 20ms
Thread 0 calculated tmp, time used: 16ms
Thread 0 calculated tmp, time used: 16ms
Thread 0 calculated tmp, time used: 15ms
因此,当并行运行时,每个线程比顺序运行需要更长的时间。有人知道为什么它不能扩展吗? std :: log实际上是如何工作的(可能是线程必须共享的东西)?有没有办法让log()函数可以扩展?谢谢!
EDIT1: 我将迭代次数增加到10e10次,但结果显示并行版本更慢,所以也许这不是线程创建时间在这里占主导地位。 4个主题:
Thread 0 calculated tmp, time used: 17890ms
Thread 2 calculated tmp, time used: 17890ms
Thread 1 calculated tmp, time used: 17892ms
Thread 3 calculated tmp, time used: 17892ms
1个帖子:
Thread 0 calculated tmp, time used: 15664ms
Thread 0 calculated tmp, time used: 15659ms
Thread 0 calculated tmp, time used: 15660ms
Thread 0 calculated tmp, time used: 15647ms
EDIT2:我让tmp变量最后打印出来,这样log()就无法优化了。但结果仍然像以前一样。还有其他想法吗?
EDIT3:因此总执行时间的加速为3.5,即使迭代次数增加,它也不会再变高。我不确定它是否合理加速,因为我期待像这样的简单程序加速3.7或3.8。
答案 0 :(得分:3)
简而言之
你完全正确。但是要全面衡量多核性能的改进,你不应该仅仅依赖于对单个线程的计时:你应该花时间测量整体执行。
多核架构似乎实现了更高的吞吐量,但是当其中几个核心处于活动状态时,每个核心略有减少。这里another benchmark(使用std::thread
代替OMP)具有类似的观察结果。
所以每个单独的日志计算都没有扩展,但是oveall系统做得非常好。
其他详情
如果您要进行一些整体的端到端测量:
int main()
{
auto common_start = std::chrono::high_resolution_clock::now();
...
auto common_end = std::chrono::high_resolution_clock::now();
cout << "Overall calculated time : " << std::chrono::duration_cast<ms>(common_end - common_start).count() << "ms" << endl;
return 0;
}
您肯定会并行观察到更好的整体表现。
这是我自己的4个帖子的时间:
Thread 2 calculated tmp, time used: 269ms
Thread 3 calculated tmp, time used: 274ms
Thread 0 calculated tmp, time used: 281ms
Thread 1 calculated tmp, time used: 289ms
Overall calculated time : 296ms
并且有一个:
Thread 0 calculated tmp, time used: 218ms
Thread 0 calculated tmp, time used: 218ms
Thread 0 calculated tmp, time used: 229ms
Thread 0 calculated tmp, time used: 224ms
Overall calculated time : 903ms
正如您已经观察到的,使用一个线程,计算执行速度提高了22%。但总的来说,多线程执行相同数量的计算需要3倍的时间。
所以关于吞吐量:与多线程的135 K-iterations / ms相比,仅以44 K-iterations / ms monothread运行。