Python 何时使用线程以及使用多少线程
我有一个工作项目。我们已经编写了一个模块,在那里作为一项任务来实现线程以改进模块。我是一个相当新的python程序员,决定尝试一下。在学习和实现线程时,我有一个类似的问题,因为我们有一个大约6个需要处理的对象的队列,所以为什么要让6个线程(或任何线程)来处理列表或队列中的对象,而处理时间可以忽略不计呢?(处理每个对象最多需要2秒钟) 所以我做了一个小实验。我想知道使用线程是否会提高性能。请参见下面我的python代码:Python 何时使用线程以及使用多少线程,python,multithreading,python-multithreading,Python,Multithreading,Python Multithreading,我有一个工作项目。我们已经编写了一个模块,在那里作为一项任务来实现线程以改进模块。我是一个相当新的python程序员,决定尝试一下。在学习和实现线程时,我有一个类似的问题,因为我们有一个大约6个需要处理的对象的队列,所以为什么要让6个线程(或任何线程)来处理列表或队列中的对象,而处理时间可以忽略不计呢?(处理每个对象最多需要2秒钟) 所以我做了一个小实验。我想知道使用线程是否会提高性能。请参见下面我的python代码: import threading import queue import m
import threading
import queue
import math
import time
results_total = []
results_calculation = []
results_threads = []
class MyThread(threading.Thread):
def __init__(self, thread_id, q):
threading.Thread.__init__(self)
self.threadID = thread_id
self.q = q
def run(self):
# print("Starting " + self.name)
process_data(self.q)
# print("Exiting " + self.name)
def process_data(q):
while not exitFlag:
queueLock.acquire()
if not workQueue.empty():
potentially_prime = True
data = q.get()
queueLock.release()
# check if the data is a prime number
# print("Testing {0} for primality.".format(data))
for i in range(2, int(math.sqrt(data)+1)):
if data % i == 0:
potentially_prime = False
break
if potentially_prime is True:
prime_numbers.append(data)
else:
queueLock.release()
for j in [1, 2, 3, 4, 5, 10, 15, 20, 25, 30, 40, 50, 75, 100, 150, 250, 500,
750, 1000, 2500, 5000, 10000]:
threads = []
numberList = list(range(1, 10001))
queueLock = threading.Lock()
workQueue = queue.Queue()
numberThreads = j
prime_numbers = list()
exitFlag = 0
start_time_total = time.time()
# Create new threads
for threadID in range(0, numberThreads):
thread = MyThread(threadID, workQueue)
thread.start()
threads.append(thread)
# Fill the queue
queueLock.acquire()
# print("Filling the queue...")
for number in numberList:
workQueue.put(number)
queueLock.release()
# print("Queue filled...")
start_time_calculation = time.time()
# Wait for queue to empty
while not workQueue.empty():
pass
# Notify threads it's time to exit
exitFlag = 1
# Wait for all threads to complete
for t in threads:
t.join()
# print("Exiting Main Thread")
# print(prime_numbers)
end_time = time.time()
results_total.append(
"The test took {0} seconds for {1} threads.".format(
end_time - start_time_total, j)
)
results_calculation.append(
"The calculation took {0} seconds for {1} threads.".format(
end_time - start_time_calculation, j)
)
results_threads.append(
"The thread setup time took {0} seconds for {1} threads.".format(
start_time_calculation - start_time_total, j)
)
for result in results_total:
print(result)
for result in results_calculation:
print(result)
for result in results_threads:
print(result)
这个测试发现质数在1到10000之间。这个设置基本上是直接从中获取的,但是我要求线程查找素数,而不是打印一个简单的字符串。这实际上不是我的真实应用程序,但我目前无法测试我为模块编写的代码。我认为这是一个很好的测试来衡量额外线程的效果。我的实际应用程序处理与多个串行设备的通信。我进行了5次测试,并取平均值。以下是图表中的结果:
关于线程和本测试,我的问题如下:
我注意到,随着工作与线程的比率接近1:1,设置线程所需的时间变得更长。因此,只有在创建一次线程并使其尽可能长时间处于活动状态的情况下,线程才有用,以处理排队速度可能快于计算速度的请求吗?不,这不是使用线程的好地方 通常,您希望在代码绑定IO的地方使用线程;也就是说,它花费大量时间等待输入或输出。一个例子可能是并行地从URL列表下载数据;代码可以开始从下一个URL请求数据,同时仍然等待上一个URL返回
这里的情况并非如此;计算素数是受cpu限制的。您认为多线程在这里是一个值得怀疑的举动,这是有道理的。目前,多线程技术非常好,在正确的应用程序中,它可以在运行时间上产生巨大的变化 然而,另一方面,它也增加了实现它的任何程序的复杂性(特别是在python中)。使用多线程时也要考虑时间惩罚,例如在执行上下文切换或实际创建线程所需的时间时发生的时间。p> 当您的程序必须处理成千上万的资源密集型任务时,这些时间惩罚是疏忽的,因为使用多线程所节省的时间远远超过准备好线程所需的一点点时间。但就你而言,我不确定你的需求是否满足这些要求。我没有深入了解你在处理什么类型的对象,但你说它们只需要2秒钟,这并不可怕,你还说你一次只需要处理6个项目。因此,平均而言,我们可以预期您的纸条的主要部分将运行12秒。在我看来,这对于多线程来说是不必要的,因为准备好线程并将指令传递给它们需要一两秒钟的时间,而在一个线程中,您的python脚本已经能够很好地处理第二个对象了 简而言之,除非您需要,否则我将保存多线程。例如,像用于基因测序的大型数据集(Python中的大事记)从中受益匪浅,因为多个线程可以帮助并发处理这些海量文件。在你的情况下,看起来目的并不能证明手段是正当的。希望这有帮助 python中的线程用于同时运行多个线程(任务、函数调用)。请注意,这并不意味着它们在不同的CPU上执行。如果程序已经使用了100%的CPU时间,Python线程将不会使程序更快。在这种情况下,您可能需要研究并行编程 发件人: 这是由于称为GIL的机制。正如Daniel指出的,python中的线程只有在具有IO绑定代码时才有用。但是,对于IO绑定的代码,最好使用在某些事件循环上运行的较轻线程(使用gevent、eventlet、asyncio或类似工具),因为这样可以轻松地运行100秒(或更多)的并行操作,而每个线程的开销很小
如果您希望使用多个CPU核心来加速执行,请查看多处理模块 这个问题应该有一个与主题相关的名称。这个想法是为了帮助将来有同样问题的人。Python中的线程确实利用了多个CPU核(在大多数使用情况下)。它不利用多个CPU。Async并不真正并行运行。例如,它只是利用了线程等待服务器响应时发生的空闲时间。为了获得最佳性能,最好将异步与多线程结合起来,有时甚至与多处理结合起来。@IonutHulub您错了。在大多数使用情况下,线程将不会使用超过1个CPU核,尤其是当