我试图理解多处理相对于线程的优势。我知道多处理绕过了全局解释器锁,但是还有什么其他的优势,线程不能做同样的事情吗?
当前回答
Threading's job is to enable applications to be responsive. Suppose you have a database connection and you need to respond to user input. Without threading, if the database connection is busy the application will not be able to respond to the user. By splitting off the database connection into a separate thread you can make the application more responsive. Also because both threads are in the same process, they can access the same data structures - good performance, plus a flexible software design.
注意,由于GIL,应用程序实际上并没有同时做两件事,但我们所做的是将数据库上的资源锁放在一个单独的线程中,这样CPU时间就可以在它和用户交互之间切换。CPU时间在线程之间分配。
Multiprocessing is for times when you really do want more than one thing to be done at any given time. Suppose your application needs to connect to 6 databases and perform a complex matrix transformation on each dataset. Putting each job in a separate thread might help a little because when one connection is idle another one could get some CPU time, but the processing would not be done in parallel because the GIL means that you're only ever using the resources of one CPU. By putting each job in a Multiprocessing process, each can run on it's own CPU and run at full efficiency.
其他回答
另一件没有提到的事情是,它取决于你使用的是什么操作系统。在Windows中,进程是昂贵的,所以线程在Windows中会更好,但在unix中,进程比它们的Windows变体更快,所以在unix中使用进程要安全得多,而且生成速度快。
Threading's job is to enable applications to be responsive. Suppose you have a database connection and you need to respond to user input. Without threading, if the database connection is busy the application will not be able to respond to the user. By splitting off the database connection into a separate thread you can make the application more responsive. Also because both threads are in the same process, they can access the same data structures - good performance, plus a flexible software design.
注意,由于GIL,应用程序实际上并没有同时做两件事,但我们所做的是将数据库上的资源锁放在一个单独的线程中,这样CPU时间就可以在它和用户交互之间切换。CPU时间在线程之间分配。
Multiprocessing is for times when you really do want more than one thing to be done at any given time. Suppose your application needs to connect to 6 databases and perform a complex matrix transformation on each dataset. Putting each job in a separate thread might help a little because when one connection is idle another one could get some CPU time, but the processing would not be done in parallel because the GIL means that you're only ever using the resources of one CPU. By putting each job in a Multiprocessing process, each can run on it's own CPU and run at full efficiency.
进程可能有多个线程。这些线程可以共享内存,并且是进程中的执行单元。
进程运行在CPU上,因此线程驻留在每个进程之下。进程是独立运行的独立实体。如果您想在每个进程之间共享数据或状态,您可以使用内存存储工具,如缓存(redis, memcache),文件或数据库。
正如问题中提到的,Python中的多处理是实现真正并行的唯一方法。多线程无法实现这一点,因为GIL阻止线程并行运行。
As a consequence, threading may not always be useful in Python, and in fact, may even result in worse performance depending on what you are trying to achieve. For example, if you are performing a CPU-bound task such as decompressing gzip files or 3D-rendering (anything CPU intensive) then threading may actually hinder your performance rather than help. In such a case, you would want to use Multiprocessing as only this method actually runs in parallel and will help distribute the weight of the task at hand. There could be some overhead to this since Multiprocessing involves copying the memory of a script into each subprocess which may cause issues for larger-sized applications.
然而,当您的任务是io绑定时,多线程就变得有用了。例如,如果您的大部分任务涉及等待api调用,那么您将使用多线程,因为为什么不在等待时在另一个线程中启动另一个请求,而不是让您的CPU无所事事。
博士TL;
多线程是并发的,用于io绑定的任务 Multiprocessing实现了真正的并行,用于cpu受限的任务
多处理
Multiprocessing通过增加cpu来提高计算能力。 多个进程同时执行。 创建流程既耗时又耗费资源。 多处理可以是对称的也可以是非对称的。
Python中的多处理库使用独立的内存空间,多个CPU核心,绕过CPython中的GIL限制,子进程是可杀死的(例如程序中的函数调用),并且更容易使用。 该模块的一些注意事项是内存占用较大,IPC稍微复杂一些,开销更大。
多线程
多线程创建单个进程的多个线程,以提高计算能力。 一个进程的多个线程并发执行。 线程的创建在时间和资源上都是经济的。
多线程库是轻量级的,共享内存,负责响应式UI,并用于I/O绑定应用程序。 该模块不可杀死,并受GIL约束。 多个线程生活在同一个进程中的同一个空间中,每个线程将执行特定的任务,有自己的代码,自己的堆栈内存,指令指针,并共享堆内存。 如果一个线程有内存泄漏,它会损害其他线程和父进程。
使用Python的多线程和多处理示例
Python 3有启动并行任务的功能。这使我们的工作更容易。
它有线程池和进程池。
下面让我们来了解一下:
ThreadPoolExecutor例子
import concurrent.futures
import urllib.request
URLS = ['http://www.foxnews.com/',
'http://www.cnn.com/',
'http://europe.wsj.com/',
'http://www.bbc.co.uk/',
'http://some-made-up-domain.com/']
# Retrieve a single page and report the URL and contents
def load_url(url, timeout):
with urllib.request.urlopen(url, timeout=timeout) as conn:
return conn.read()
# We can use a with statement to ensure threads are cleaned up promptly
with concurrent.futures.ThreadPoolExecutor(max_workers=5) as executor:
# Start the load operations and mark each future with its URL
future_to_url = {executor.submit(load_url, url, 60): url for url in URLS}
for future in concurrent.futures.as_completed(future_to_url):
url = future_to_url[future]
try:
data = future.result()
except Exception as exc:
print('%r generated an exception: %s' % (url, exc))
else:
print('%r page is %d bytes' % (url, len(data)))
ProcessPoolExecutor
import concurrent.futures
import math
PRIMES = [
112272535095293,
112582705942171,
112272535095293,
115280095190773,
115797848077099,
1099726899285419]
def is_prime(n):
if n % 2 == 0:
return False
sqrt_n = int(math.floor(math.sqrt(n)))
for i in range(3, sqrt_n + 1, 2):
if n % i == 0:
return False
return True
def main():
with concurrent.futures.ProcessPoolExecutor() as executor:
for number, prime in zip(PRIMES, executor.map(is_prime, PRIMES)):
print('%d is prime: %s' % (number, prime))
if __name__ == '__main__':
main()
推荐文章
- 在python中,年龄从出生日期开始
- 使用pip安装SciPy
- 在Python中,我应该如何测试变量是否为None, True或False
- 如何在Python中从毫秒创建datetime ?
- 如何解窝(爆炸)在一个熊猫数据帧列,成多行
- 如何使用pip安装opencv ?
- 在pip冻结命令的输出中“pkg-resources==0.0.0”是什么
- 格式y轴为百分比
- 熊猫连接问题:列重叠但没有指定后缀
- 为什么空字典在Python中是一个危险的默认值?
- 在Python中,冒号等于(:=)是什么意思?
- Python "SyntaxError:文件中的非ascii字符'\xe2' "
- 等待未来的名单
- 如何从psycopg2游标获得列名列表?
- Python中dict对象的联合