【问题标题】:C++ thread performanceC++ 线程性能
【发布时间】:2014-01-25 01:27:09
【问题描述】:

我做了一个小程序来观察使用两个线程的速度。我正在计时填充数组的过程。 A 主线程和 thread1 调用 function_1 来初始化数组的不同部分。我期待通过使用两个线程来看到更快的结果。相反,我的时间变慢了,注释掉的代码执行得更快。我哪里错了?

#include <chrono>
#include <iostream>
#include <vector>
#include <thread>


void function_1(int I, int J, int *B){
    for (int i = I; i<(J+1); i++) {
        B[i] = 100;
       //std::cout << B[i] << std::endl;
    }
}

int *count;

int main(int argc, const char * argv[])
{
    count = new int[20000];

    std::chrono::steady_clock::time_point t1 = std::chrono::steady_clock::now();
    //function_1(0, 19999, count);
    std::thread thread1(function_1, 0, 9999, count);
    thread1.join();
    function_1(10000, 19999, count);

    std::chrono::steady_clock::time_point t2 = std::chrono::steady_clock::now();
    auto time_span = std::chrono::duration_cast<std::chrono::microseconds>(t2 - t1).count();
    std::cout << "time taken is :" <<time_span << " ms"<<std::endl;

    return 0;
}

【问题讨论】:

    标签: c++ arrays multithreading performance


    【解决方案1】:

    您通过在创建后立即加入 thread1 来同步执行示例代码。 main() 中的执行将阻塞,直到该线程终止处理,然后将移动到 function_1(10000, 19999, count); 为了利用额外的线程,请尝试在 main 中调用 function_1(10000, 19999, count); 之后将 join 调用移动。

    【讨论】:

    • 我在 main 调用 function_1 之后移动了 thread1.join()。由于某种原因,使用两个线程仍然比使用一个带有注释代码的线程慢。
    • 测试似乎有点太琐碎了。线程管理很可能会对您的性能产​​生负面影响。线程并不是真正免费的并行运行方式。
    • @Mario:这确实是少量的工作。您可以尝试将数组放大 10 或 100 倍。
    • @Blastfurnace 谢谢。在我制作了 100 万个元素的数组后,我开始注意到不同之处。
    【解决方案2】:
    std::thread thread1(function_1, 0, 9999, count);
    thread1.join();
    function_1(10000, 19999, count);
    

    主线程将等待thread1 完成工作,然后再调用function_1。这和调用是一样的

    function_1(...)
    function_1(...)
    

    在主线程上,只需要管理线程带来的额外成本。在主线程上调用 function_1 之后,您可能想要 join()

    此外,您应该增加工作量以使测试更加相关。线程并不是真正快速完成工作的免费方式。在决定它们是否与您的情况相关之前,您需要考虑维护线程的成本。

    【讨论】:

    • 我将主线程对 function_1 的调用移动到 thread1 的实例化下方和 thread1.join() 之前。与原始结果相比,时间略有改进。但由于某种原因,它并不比使用注释掉的代码使用一个线程快。
    【解决方案3】:

    当手头的任务只包括填充内存时,您不太可能看到重大改进。

    问题很简单:单核可能会使内存的全部带宽饱和。在这种情况下,添加更多线程并没有多大好处,除非您的计算机具有多个处理器,而不仅仅是单个插槽中的多个内核。

    使用多个套接字,您可以通过在不同的物理处理器上运行不同的线程来提高速度,每个物理处理器都有自己的内存连接。但是,为了使其有效,您通常需要使用一些非标准函数调用来确保每个线程在单独的物理处理器上运行,并确保在每个处理器上运行的线程写入该处理器本地的内存。

    这些都不是火箭科学,但它们也不一定是微不足道的。即使是最简单的,至少有一小部分代码几乎肯定是不可移植的。

    要查看多线程的主要收益,您通常希望执行包含各种不同类型工作的混合任务:例如,一些受 I/O 限制,一些受内存限制,还有一些受处理器限制。在这种情况下,从多个线程中获得显着的加速要容易得多。如果你不能拥有它,那么严重受处理器限制的东西可能是第二选择。假设您可以在线程之间很少或不同步的情况下这样做,那么您很有可能获得大致线性的加速(即,N 个内核执行代码的速度大约是一个内核的 N 倍)。

    【讨论】:

      猜你喜欢
      • 2013-10-16
      • 2012-07-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-04-23
      • 1970-01-01
      • 1970-01-01
      • 2014-12-31
      相关资源
      最近更新 更多