提问人:coding-cat 提问时间:10/31/2023 更新时间:11/2/2023 访问量:62
python 多线程(FIle read I/O)不是奇视吗?
python multithread ( FIle read I/O ) is not parallism?
问:
在 python 文档中,python 多线程值得执行 FILE I/O、网络 I/O、numpy 等任务
所以我尝试了下面的代码
import threading
import os
import time
import multiprocessing
# create test file
def create_test_file():
if os.path.exists("./test.txt"):return 1
with open("./test.txt","w") as fd :
for i in range(100000):
text = str(i) * 3
text += "\n"
fd.write(text)
create_test_file()
def file_read():
for _ in range(100):
with open("./test.txt","r") as fd :
while True :
line = fd.readline()
if not line : break
if __name__ == "__main__":
start_time = time.time()
file_read()
file_read()
file_read()
file_read()
print("sequential task %.2f"%(time.time() - start_time))
t1 = threading.Thread(target=file_read)
t2 = threading.Thread(target=file_read)
t3 = threading.Thread(target=file_read)
t4 = threading.Thread(target=file_read)
start_time = time.time()
t1.start()
t2.start()
t3.start()
t4.start()
t1.join()
t2.join()
t3.join()
t4.join()
print("multi_thread task %.2f"%(time.time() - start_time))
p1 = multiprocessing.Process(target=file_read)
p2 = multiprocessing.Process(target=file_read)
p3 = multiprocessing.Process(target=file_read)
p4 = multiprocessing.Process(target=file_read)
start_time = time.time()
p1.start()
p2.start()
p3.start()
p4.start()
p1.join()
p2.join()
p3.join()
p4.join()
print("multi_process task %.2f" % (time.time() - start_time))
但结果是
顺序任务 7.25 multi_thread任务 7.58 multi_process任务 2.45
为什么多线程效率不高?
我知道python有GIL,但是在python文档(https://wiki.python.org/moin/GlobalInterpreterLock )
事后看来,GIL 并不理想,因为它会阻止多线程 CPython 程序在某些情况下充分利用多处理器系统。幸运的是,许多潜在的阻塞或长时间运行的操作,例如 I/O、图像处理、
为什么多线程比顺序任务慢???GIL 仍在工作 文件读取 I/O??
答:
顶级域名;file.read
确实释放了 gil,但很难让文件读取 Python 代码中的限制瓶颈。
每当你真的想知道用 c/c++ 编写的 python 函数(或库函数)是否释放 GIL 时;您查找宏:,并且确实在“FileUtils.c”中确实释放了GIL。现代操作系统和固态硬盘(甚至是硬盘)在从文件中读取数据的速度非常快,因此,如果这是程序中唯一可以利用并行性的部分,那么您真的不会看到线程的太多优势。这就是为什么使用它的原因,它可以让您绕过 GIL。Py_BEGIN_ALLOW_THREADS
_Py_read
multiprocessing
但是,如果您从套接字而不是文件读取数据速率可能受到网络硬件或互联网服务提供商的限制,则该调用可能确实是限制因素,并且将其并行可能确实会有所帮助。最终,许多这些“等待 IO”任务都同样出色,基本上允许您对许多 IO 任务进行排队,然后在它们完成时响应它们。这是以显式单线程方式完成的,因此没有并行处理的错觉,只是您可以对可能需要一段时间才能响应的事情进行并行等待。read
asyncio
numpy
正如您在某些计算中提到的,也会释放 GIL,但应该注意的是,numpy 的底层 BLAS 库可能已经在使用多线程,并且通常很难通过在此基础上实现自己的多线程来提高性能。我最近观看的这段视频介绍了从一般矩阵乘法(点积)函数中实际提取最大性能所需的一些高级主题。它基本上以“只使用现有的库”结束,因为大量非常聪明的人已经将其优化到极致。在本例中,该库是“英特尔数学核心函数库”,它可能与numpy使用的库相同,具体取决于它的编译方式。
评论
read_file
000\n
999999999999999\n
)