C++ 为什么6-7线程比20线程快?
在学校,我们被介绍给C++11线程。老师给了我们一个简单的评估来完成,那就是用20个线程制作一个基本的网络爬虫。对我来说,线程是相当新的,尽管我确实了解基本知识 我想说的是,我不是在寻找一个人来完成我的评估,因为它已经完成了。我只想了解为什么使用6个线程总是比使用20个线程快 请参阅下面的代码示例 main.cpp: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
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();
}