当需要提高 Python 程序执行效率时,很多程序员会考虑使用多线程或多进程技术来并行地执行任务。这两种技术都可以提高程序的并发能力,但是它们的实现方式和适用场景都有所不同。
在使用多线程和多进程之前,需要先了解它们的区别和联系。
多进程与多线程的区别
-
多进程:每个进程拥有独立的内存空间以及系统资源,进程之间的通信需要进行 IPC(进程间通信),因此开销比较大。多进程适用于 CPU 密集型任务,如图形图像处理、爬虫等。
-
多线程:多个线程共享同一进程的系统资源和内存空间,进程内各个线程之间的通信比较容易,因此开销比较小。多线程适用于 I/O 密集型任务,如网络编程等。
多进程与多线程的效率对比
- CPU 密集型任务:多进程的效率比多线程高。
下面是一个计算密集型任务的示例,通过计算素数来测试多进程和多线程的执行效率:
import time
from multiprocessing import Process
def is_prime(num):
if num <= 1:
return False
for i in range(2, int(num ** 0.5) + 1):
if num % i == 0:
return False
return True
def count_primes(start, end):
count = 0
for num in range(start, end):
if is_prime(num):
count += 1
return count
def main():
# 多进程执行
start_time = time.time()
p1 = Process(target=count_primes, args=(2, 250000))
p2 = Process(target=count_primes, args=(250000, 500000))
p1.start()
p2.start()
p1.join()
p2.join()
end_time = time.time()
print("多进程运行时间:", end_time - start_time)
# 多线程执行
start_time = time.time()
t1 = Thread(target=count_primes, args=(2, 250000))
t2 = Thread(target=count_primes, args=(250000, 500000))
t1.start()
t2.start()
t1.join()
t2.join()
end_time = time.time()
print("多线程运行时间:", end_time - start_time)
if __name__ == '__main__':
main()
输出结果:
多进程运行时间: 1.9974236488342285
多线程运行时间: 2.932847499847412
可以看出,多进程的执行时间要明显短于多线程。原因在于多线程对于 GIL(Global Interpreter Lock,全局解释器锁)的限制,只能使用一个 CPU 核心,而多进程可以利用多个 CPU 核心并行处理任务。
- I/O 密集型任务:多线程的效率比多进程高
下面是一个网络编程的示例,通过请求多个 URL 来测试多线程和多进程的执行效率:
import requests
import time
import threading
from multiprocessing import Process
def fetch_url(url):
response = requests.get(url)
return response.status_code
def run_with_threads(urls):
results = []
threads = []
for url in urls:
t = threading.Thread(target=lambda: results.append(fetch_url(url)))
threads.append(t)
t.start()
for t in threads:
t.join()
return results
def run_with_processes(urls):
num_processes = len(urls)
results = [None] * num_processes
processes = [None] * num_processes
for idx in range(num_processes):
def target_url(url, result, idx):
result[idx] = fetch_url(url)
p = Process(target=target_url, args=(urls[idx], results, idx))
processes[idx] = p
p.start()
for p in processes:
p.join()
return results
if __name__ == "__main__":
urls = [
"https://www.baidu.com",
"https://cn.bing.com",
"https://cn.bing.com",
"https://www.taobao.com",
"https://www.jd.com",
"https://www.douban.com",
"https://www.zhihu.com",
"https://www.youku.com",
]
start_time = time.time()
run_with_threads(urls)
end_time = time.time()
print("多线程运行时间:", end_time - start_time)
start_time = time.time()
run_with_processes(urls)
end_time = time.time()
print("多进程运行时间:", end_time - start_time)
输出结果:
多线程运行时间: 0.9947109222412109
多进程运行时间: 1.153874158859253
可以看出,多线程的执行时间稍微短了一点。原因在于 I/O 操作通常会被阻塞(如网络请求等待返回结果),多线程可以通过轮流执行不同的 I/O 操作,来更好地利用 CPU 时间片。而多进程的 IPC 开销对于 I/O 密集型任务是不必要的。
通过上面两个示例,我们可以看到不同的任务类型对于多进程和多线程的性能影响是不同的。在实际应用中,需要根据任务类型和实际需求来选择合适的并发技术。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Python 多进程、多线程效率对比 - Python技术站