Python 我是否过度浏览IO绑定的web刮削线程?

Python 我是否过度浏览IO绑定的web刮削线程?,python,multithreading,cpu,Python,Multithreading,Cpu,TL;医生: 如果我生成10个web请求,每个请求都在自己的线程上,CPU有4个线程的限制,这可以吗?线程是IO绑定的,所以在等待服务器响应时处于空闲状态(我相信)。如果同时返回超过4个线程,CPU将如何处理 我有一个脚本,当前通过http.client.HTTPSConnection为我需要下载的每个文件(每个文件位于唯一的URL)启动一个新线程。在最大值时,我可能需要生成730个线程。我已经这样做了,因为线程都是IO绑定的工作(下载并保存到文件),但我不确定它们是并行执行还是CPU一次只执行

TL;医生: 如果我生成10个web请求,每个请求都在自己的线程上,CPU有4个线程的限制,这可以吗?线程是IO绑定的,所以在等待服务器响应时处于空闲状态(我相信)。如果同时返回超过4个线程,CPU将如何处理

我有一个脚本,当前通过
http.client.HTTPSConnection
为我需要下载的每个文件(每个文件位于唯一的URL)启动一个新线程。在最大值时,我可能需要生成730个线程。我已经这样做了,因为线程都是IO绑定的工作(下载并保存到文件),但我不确定它们是并行执行还是CPU一次只执行一个集合。文件大小介于20MB到110MB之间的总运行时间大约为15分钟

我的CPU是四核的,没有超线程。这意味着它在任何给定的时间只能同时支持4个线程。既然工作是IO绑定的,而不是CPU绑定的,那么我是否仍然受到只有4个并发线程的限制

我想让人困惑的是,如果说我只发送了10个线程上的1个请求,我不确定会发生什么样的事件序列;如果他们同时返回会发生什么?或者CPU如何选择在进入下一个可用线程之前完成哪4个线程


在所有这一切之后,如果CPU一次只处理4个线程,我认为生成我需要的尽可能多的IO线程(因为它们在等待服务器响应时会处于空闲状态)仍然是明智的,对吗?

四核CPU上可以有明显多于4个IO绑定线程。但是,您确实希望有一些最大值。即使是IO绑定的进程也会在某些时候使用CPU。例如,当接收到数据包时,需要处理该数据包以更新TCP状态。如果从套接字读取数据并写入文件,在大多数情况下,需要一些CPU将字符从套接字缓冲区复制到文件缓冲区。如果使用TLS,通常需要CPU来解密和加密数据。因此,即使是主要执行IO的线程也会使用一些CPU。最终,您使用CPU的一小部分时间将累积起来并消耗可用的CPU资源。 另外,请注意,在Python中,由于全局解释器锁,一次只能有一个线程使用CPU运行Python代码。因此,在执行诸如等待传出连接之类的操作时,通常不会持有GIL。在此期间,可以运行其他线程。然而,在从套接字或文件进行读写的部分时间内,GIL将被保持。对于大多数常见的工作负载,当线程需要一个CPU的时间部分达到一个完整的CPU而不是四个完整的CPU时,应用程序的性能可能会达到最大值。 您可能会发现,使用
asyncio
或其他一些事件驱动的体系结构可以提供更好的性能。如果为true,这通常是因为事件驱动模型更能减少跨线程资源争用。
在回答您的编辑问题时,我不认为10个线程会是一个问题

我确实读过关于GIL的文章。“一次运行一个python代码”到底是什么意思?整个程序是Python!当我发送
conn.request()
时,我知道没有代码正在运行,因为该线程正在等待服务器响应。返回数据后,线程将继续执行下一行代码(这是一个使用open()将返回的数据写入文件的
)。在文件中接收和写入数据是否仍被视为IO绑定,因此不受GIL的约束?所有线程生成后,只有我的主线程(正在执行线程状态的
队列
)始终处于
状态,而
状态。在等待连接时,线程可以释放GIL,并让其他线程运行。然而,当建立连接时,GIL可能会被短暂地抓取以更新python对象。我的观点是,与4个CPU的工作价值相比,最高工作价值更接近1个CPU的工作价值。你能详细说明一下“可能累计”和“最高工作价值更接近1个CPU的工作价值”吗?我编辑了答案,试图回答你的评论。感谢更新。最后一件事,当您声明“一个完整的CPU而不是四个完整的CPU”时,我只有一个CPU和四个内核;你是说一个完整的核心?如果吉尔只是让1运行一次,即使吉尔是非常短暂的。如果你使用3.4 +,考虑考虑使用AssiCIO任务或第三方包中的一个做类似的事情。任务切换的开销应该比线程切换小。请注意,您不能“同时”得到响应,因为您的以太网端口是一条串行线,一次传输一个数据包。@TerryJanReedy很高兴知道!我得调查一下。然而,我只是想更好地理解进程/线程顺序以及对CPU体系结构的影响。因此,当我启动100个线程(出于某些奇怪的原因!)并且数据从服务器返回到每个线程时,它一次返回1个线程,CPU只是在执行线程中剩余的工作(一次最多4个线程)?如果您有一个指向CPU如何管理/处理线程的概述的链接,那么这是最理想的!