进程/线程 和 I/O操作
Posted 小小菜_v
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了进程/线程 和 I/O操作相关的知识,希望对你有一定的参考价值。
线程
线程是操作系统能进行运算调度的最小单位。
进程
进程是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础。
Python多进程和多线程的使用场景
版权声明:本文为CSDN博主「大帅不是我」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/hhs_1996/article/details/114317308
Python多进程适用的场景:计算密集型(CPU密集型)任务
Python多线程适用的场景:IO密集型任务
计算密集型任务一般指需要做大量的逻辑运算,比如上亿次的加减乘除,使用多核CPU可以并发提高计算性能。
IO密集型任务一般指输入输出型,比如文件的读取,或者网络的请求,这类场景一般会遇到IO阻塞,使用多核CPU来执行并不会有太高的性能提升。
下面使用一台64核的虚拟机来执行任务,通过示例代码来区别它们,
示例1:执行计算密集型任务,进行1亿次运算
使用多进程
from multiprocessing import Process
import os, time
# 计算密集型任务
def work():
res = 0
for i in range(100 * 100 * 100 * 100): # 亿次运算
res *= i
if __name__ == "__main__":
l = []
print("本机为", os.cpu_count(), "核 CPU") # 本机为64核
start = time.time()
for i in range(4):
p = Process(target=work) # 多进程
l.append(p)
p.start()
for p in l:
p.join()
stop = time.time()
print("计算密集型任务,多进程耗时 %s" % (stop - start))
使用多线程
from threading import Thread
import os, time
# 计算密集型任务
def work():
res = 0
for i in range(100 * 100 * 100 * 100): # 亿次运算
res *= i
if __name__ == "__main__":
l = []
print("本机为", os.cpu_count(), "核 CPU") # 本机为64核
start = time.time()
for i in range(4):
p = Thread(target=work) # 多线程
l.append(p)
p.start()
for p in l:
p.join()
stop = time.time()
print("计算密集型任务,多线程耗时 %s" % (stop - start))
两段代码输出:
本机为 64 核 CPU
计算密集型任务,多进程耗时 6.864224672317505
本机为 64 核 CPU
计算密集型任务,多线程耗时 37.91042113304138
说明:上述代码中,分别使用4个多进程和4个多线程去执行亿次运算,多进程耗时6.86s,多线程耗时37.91s,可见在计算密集型任务场景,使用多进程能大大提高效率。
另外,当分别使用8个多进程和8个多线程去执行亿次运算时,耗时差距更大,输出如下:
本机为 64 核 CPU
计算密集型任务,多进程耗时 6.811635971069336
本机为 64 核 CPU
计算密集型任务,多线程耗时 113.53767895698547
可见在64核的cpu机器下,同时使用8个多进程和4个多进程效率几乎一样。而使用多线程则就效率较慢。要最高效地利用CPU,计算密集型任务同时进行的数量应当等于CPU的核心数
示例2:400次,阻塞两秒,读取文件
使用多进程(4核cpu)
from multiprocessing import Process
import os, time
# I/0密集型任务
def work():
time.sleep(5) # 阻塞两秒
if __name__ == "__main__":
l = []
print("本机为", os.cpu_count(), "核 CPU")
start = time.time()
for i in range(1000):
p = Process(target=work) # 多进程
l.append(p)
p.start()
for p in l:
p.join()
stop = time.time()
print("I/0密集型任务,多进程耗时 %s" % (stop - start))
使用多线程(4核cpu)
from threading import Thread
import os, time
# I/0密集型任务
def work():
time.sleep(5) # 阻塞两秒
if __name__ == "__main__":
l = []
print("本机为", os.cpu_count(), "核 CPU")
start = time.time()
for i in range(1000):
p = Thread(target=work) # 多线程
l.append(p)
p.start()
for p in l:
p.join()
stop = time.time()
print("I/0密集型任务,多线程耗时 %s" % (stop - start))
输出:
本机为 64 核 CPU
I/0密集型任务,多进程耗时 12.28218412399292
本机为 64 核 CPU
I/0密集型任务,多线程耗时 5.399136066436768
说明:python的多线程有于GIL锁的存在,无论是多少核的cpu机器,也只能使用单核,从输出结果来看,对于IO密集型任务使用多线程比较占优。
FAQ:执行多进程的io密集型任务时,报了一个错:
OSError: [Errno 24] Too many open files
原因:linux系统限制
ulimit -n
# 输出 1024
解决:(临时提高系统限制,重启后失效)
ulimit -n 10240
I/O
作者:张冬
链接:https://www.zhihu.com/question/24374518/answer/27714652
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
关于如何才算一个IO的问题,我可以在这里简要讲解,IO在不同层次有不同的概念和单位。
一次IO就是一次请求,对于磁盘来说,一个IO就是读或者写磁盘的某个或者某段扇区,
读写完了,这个IO也就结束了。
至于transaction,就是更高层的内容了,transaction往往与业务逻辑有关系。
比如你去银行存一笔钱,你存这笔钱的过程中,服务器向数据库中写入的所有关联的操作就算是一个transaction
,而完成这一个transaction,往往对应了底层对磁盘的多次IO。
比如,读出数据库中原来的数据,比如你原来存款是10000元,他读出来了,
然后显示在柜台终端上,然后操作员存入5000元,数据传输到数据库服务器,
数据库服务器在内存中更改这个数值,从10000更改为1.5000,然后数据库Flush的时候,
将对应的数据库写入磁盘,完成后,柜台终端显示成功。这个过程中对应了多次磁盘IO。
补充几点:IO类型有多种,数据型IO和非数据型IO。前者是指IO请求中包含读写扇区的数据的,后者是指IO中不包含扇区数据,而是承载其他信息的,如SCSI协议中的很多操作码,
比如0×01就是zero指令,命令磁盘自行向所有扇区中写0。
或者诸如report LUN这种常见的指令,它们是命令磁盘做一些其他的动作,而不是真正的读写扇区中的数据。
对于网络文件系统来说,也有数据型IO和非数据型IO,前者比如读写操作,后者比如NFS中的mount、fsinfo、fsstat、getattr等。
这就是transaction与IO的关系
以上是关于进程/线程 和 I/O操作的主要内容,如果未能解决你的问题,请参考以下文章