在许多有关 python 多线程的堆栈溢出问答中,我读到 python 有 GIL,因此多线程比顺序代码慢。
但在我的代码中它看起来并不像
这是多线程代码
代码已更新2023年2月21日
import threading
import time
global_v = 0
thread_lock = threading.Lock()
def thread_test(num):
thread_lock.acquire()
global global_v
for _ in range(num):
global_v += 1
thread_lock.release()
# thread run
thread_1 = threading.Thread(target=thread_test, args=(9_000_000,))
thread_2 = threading.Thread(target=thread_test, args=(9_000_000,))
thread_3 = threading.Thread(target=thread_test, args=(9_000_000,))
thread_4 = threading.Thread(target=thread_test, args=(9_000_000,))
thread_5 = threading.Thread(target=thread_test, args=(9_000_000,))
thread_start = time.perf_counter()
# start thread
thread_1.start()
thread_2.start()
thread_3.start()
thread_4.start()
thread_5.start()
thread_end = time.perf_counter()
thread_1.join()
thread_2.join()
thread_3.join()
thread_4.join()
thread_5.join()
print(f"multithread run takes {thread_end-thread_start:.5f} sec")
# nomal run (sequential code)
def increment():
global nomal_result
for _ in range(45_000_000):
nomal_result += 1
nomal_result = 0
start_time = time.perf_counter()
increment()
end_time = time.perf_counter()
print(f"nomal run takes {end_time-start_time:.5f} sec")
结果是
multithread run takes 0.21226 sec
nomal run takes 2.09347 sec
因此我的问题是这样的
Q1.为什么Python中的线程比顺序代码更快?
Q2。带锁的多线程和顺序代码有什么区别(我认为如果使用锁,代码的工作方式就像带阻塞的顺序代码)
请告诉我 !
感谢您
蟒蛇版本3.8.10
附注我移动第三个问题Python多线程加锁速度更快,为什么? https://stackoverflow.com/questions/75516141/python-multi-threading-with-lock-is-much-faster-why
看起来这是由 CPython 处理全局变量的方式引起的。这个顺序版本比我的机器上使用 CPython 3.11 的并发版本更快:
def increment():
nomal_result = 0
for _ in range(5_000_000):
nomal_result += 1
nomal_result = 0
start_time = time.perf_counter()
increment()
end_time = time.perf_counter()
print(f"nomal run takes {end_time-start_time:.5f} sec")
因此,您的多线程代码并不比顺序代码快。性能差距可能是由于两个版本之间的 CPython 优化不同造成的,而且大多是无关紧要的。
GIL 不会阻止all代码有效地多线程。这是一个简单的反例:
import threading
import time
def thread_test():
time.sleep(1.0)
thread_start = time.perf_counter()
thread_1 = threading.Thread(target=thread_test)
thread_2 = threading.Thread(target=thread_test)
thread_1.start()
thread_2.start()
thread_1.join()
thread_2.join()
thread_end = time.perf_counter()
print(f"Task duration: {thread_end - thread_start:.5f} sec")
相比:
import time
def thread_test():
time.sleep(1.0)
thread_start = time.perf_counter()
thread_test()
thread_test()
thread_end = time.perf_counter()
print(f"Task duration: {thread_end - thread_start:.5f} sec")
多线程版本只需要1秒,而顺序版本需要2秒。
一般来说,大量调用 C 函数并释放 GIL 的代码(如 NumPy)和 IO 绑定的代码(网络调用)将受益于 Python 中的多线程。相反,CPU 密集型任务(例如您的代码)不会从中受益。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)