Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/140.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 为什么6-7线程比20线程快?_C++_Multithreading_Visual Studio 2013_Windows 8.1_Stdthread - Fatal编程技术网

C++ 为什么6-7线程比20线程快?

C++ 为什么6-7线程比20线程快?,c++,multithreading,visual-studio-2013,windows-8.1,stdthread,C++,Multithreading,Visual Studio 2013,Windows 8.1,Stdthread,在学校,我们被介绍给C++11线程。老师给了我们一个简单的评估来完成,那就是用20个线程制作一个基本的网络爬虫。对我来说,线程是相当新的,尽管我确实了解基本知识 我想说的是,我不是在寻找一个人来完成我的评估,因为它已经完成了。我只想了解为什么使用6个线程总是比使用20个线程快 请参阅下面的代码示例 main.cpp: do { for (size_t i = 0; i < THREAD_COUNT; i++) { threads[i] = std::thre

在学校,我们被介绍给C++11线程。老师给了我们一个简单的评估来完成,那就是用20个线程制作一个基本的网络爬虫。对我来说,线程是相当新的,尽管我确实了解基本知识

我想说的是,我不是在寻找一个人来完成我的评估,因为它已经完成了。我只想了解为什么使用6个线程总是比使用20个线程快

请参阅下面的代码示例

main.cpp:

do
{
    for (size_t i = 0; i < THREAD_COUNT; i++)
    {
        threads[i] = std::thread(SweepUrlList);
    }

    for (size_t i = 0; i < THREAD_COUNT; i++)
    {
        threads[i].join();
    }

    std::cout << std::endl;
    WriteToConsole();
    listUrl = listNewUrl;
    listNewUrl.clear();
} while (listUrl.size() != 0);

欢迎您提供所有答案,如果可能,请链接到您找到的任何文档以回答此问题

这是一个相当普遍的线程问题,其核心是:

你们正在演示的是线程。操作系统将使用各种线程,并在当前无法工作的地方安排工作

假设你有4个内核和超线程,你有8个处理器可以承载负载,但也有其他应用程序(操作系统、C++调试器和你的应用程序启动)。 从理论上讲,在大约8个密集线程之前,您的性能可能还可以。在达到处理器可以有效使用的线程数之后,线程开始相互竞争资源。这可以通过性能差看出(特别是在密集型应用程序和紧密循环的情况下)


最后,这是一个简单的答案,但我怀疑你看到了什么。

简单的答案是瓶颈。你正在做的事情造成了瓶颈。发生这种情况时,速度会减慢。这可能是由于您正在与某个对象建立的活动连接的数量,或者仅仅是线程数量和内存大小的额外开销(请参阅下面关于内核是这些阻塞之一的回答)

您将需要设置一系列监视器来调查您的瓶颈在哪里,以及需要改变什么才能实现规模。每个行业的许多系统每天都面临这个问题。在一端打开油门并不等于在另一端增加相同的输出。在某些情况下,它会降低另一端的输出


以离开大厅的个人为例。目标是尽快让100人离开大楼。如果单个文件每1秒产生1人,则需要100秒才能清除建筑物。我们很多人可以通过两人并排出去,50秒来清理大楼,从而将时间缩短一半。如果我们把他们8人同时送出呢。门只有2米宽,所以8个平行的门相当于4米,只有第一排的50%能通过。其他4个将导致下一行阻塞,依此类推。根据速率的不同,这可能会导致临时阻塞并将时间增加10倍。

线程是一种操作系统结构。基本上,每个线程的状态(基本上是所有CPU的寄存器和虚拟内存映射[它是进程构造的一部分])都由操作系统保存。一旦操作系统给了这个特定线程“执行时间”,它就会恢复这个状态并让它运行。一旦此时间结束,它必须保存此状态。保存一个特定线程的状态并恢复另一个线程的过程被调用,它需要大量的时间(通常在数百到数千个CPU周期之间)

上下文切换也有额外的惩罚。处理器的一些缓存(如虚拟内存转换缓存,称为)必须被刷新,流水线指令被丢弃等等。通常,您希望尽可能减少上下文切换

如果您的CPU有4个内核,则超过4个线程可以同时运行。如果您尝试在一个4核系统上运行20个线程,那么操作系统必须管理这些线程之间的时间,这样看起来它们是并行运行的。例如,线程1-4将运行50毫秒,然后5-9将运行50毫秒,等等


因此,如果您的所有线程都在运行CPU密集型操作,那么让程序使用与内核相同数量的线程(在windows中有时称为“处理器”)通常是最有效的。如果线程数多于内核数,则必须进行上下文切换,并且可以最小化开销。

一般来说,线程数越多越好。更多线程通过两种方式提供价值:更高的并行性和更少的阻塞。更高的内存、更高的上下文切换和更高的资源争用会对线程造成更大的伤害

为了获得更高的并行性,线程数越多的值通常在实际可用内核数的1-2倍之间最大化。如果您的线程已经绑定了CPU,那么最大值通常是1倍的内核数

较少阻塞的价值更难量化,并且取决于您正在执行的工作类型。如果您是IO绑定的,并且您的线程主要等待IO就绪,那么更多的线程可能是有益的

但是,如果线程之间有共享状态,或者正在线程之间进行某种形式的消息传递,则会遇到同步和争用问题。随着线程数量的增加,这些类型的开销以及上下文切换在执行任务时所占的时间越长

是一种有用的度量方法,用于确定更高的并行性是否会实际改善作业的总运行时间

您还必须注意,增加的并行性不会超过其他资源,如总内存、磁盘或网络吞吐量。一旦您已经饱和了当前的瓶颈,您将不会看到通过增加线程数量来提高性能

在进行任何性能调优之前,了解主要的资源瓶颈是什么是很重要的。有很多工具可以进行系统范围的资源监控。在Linux上,一个非常有用的工具是
dstat
。在Windows上,您可以使用T
while (1)
{
    mutextGetNextUrl.lock();
    std::set<std::string>::iterator it = listUrl.begin();
    if (it == listUrl.end())
    {
        mutextGetNextUrl.unlock();
        break;
    }
    std::string url(*it);
    listUrl.erase(*it);
    mutextGetNextUrl.unlock();
    ExtractEmail(url, listEmail);
    std::cout << ".";
}
if(email.length() != 0)
{
    mutextInsertNewEmail.lock();
    ListEmail.insert(email);
    mutextInsertNewEmail.unlock();
}