c ++ std :: log函数无法扩展

时间:2016-07-09 07:59:37

标签: c++ multithreading c++11

我正在运行一段代码来测试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。

1 个答案:

答案 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运行。