我正在将文本行读入“行”列表中,并尝试使用多线程加速。但是,它根本无法加速。我在Mac上观看cpu的使用情况,发现使用多线程的cpu占145%,但没有加速。
from concurrent.futures import ThreadPoolExecutor
te = TimeExtractor()
def time_test(text):
result = te.compute_time(text)
# print(result)
if __name__ == "__main__":
start = time.time()
rows = []
with open('data/data.csv', 'r', encoding='utf') as f:
csvreader = csv.DictReader(f, delimiter='\t', quoting=csv.QUOTE_ALL)
for row in csvreader:
rows.append(row['text'])
with ThreadPoolExecutor(4) as executor:
results = executor.map(time_test, rows)
end = time.time()
print(end-start)
print('Done!!!')
使用多线程的代码的简化版本是:
import time
import concurrent.futures
from multiprocessing import cpu_count
num_cpu = cpu_count()
print("CPU Count: ", num_cpu) # cpu_count doesnt really matter
e = concurrent.futures.ThreadPoolExecutor(num_cpu)
def cpu_intensive_task(i):
print(i, ' : start task')
count = 10000000 * (i+1)
while count > 0:
count -= 1
print(i, ' : end task')
return i
start = time.time()
for i in e.map(cpu_intensive_task, range(10)):
print(i, ' : in loop')
end = time.time()
print('LOOP DONE')
print('Total Time taken: ', (end-start))
输出:
CPU Count: 8
0 : start task
1 : start task
2 : start task
3 : start task
4 : start task
5 : start task
7 : start task
6 : start task
0 : end task
8 : start task
0 : in loop
1 : end task
9 : start task
1 : in loop
2 : end task
2 : in loop
3 : end task
3 : in loop
4 : end task
4 : in loop
5 : end task
5 : in loop
6 : end task
6 : in loop
7 : end task
7 : in loop
8 : end task
8 : in loop
9 : end task
9 : in loop
LOOP DONE
Total Time taken: 30.59025502204895
注意:仅在所有线程完成后才退出循环
没有多线程的相同代码:
import time
def cpu_intensive_task(i):
print(i, ' : start task')
count = 10000000 * (i+1)
while count > 0:
count -= 1
print(i, ' : end task')
return i
start = time.time()
for i in range(10):
cpu_intensive_task(i)
print(i, ' : in loop')
end = time.time()
print('LOOP DONE')
print('Time taken: ', (end-start))
输出:
0 : start task
0 : end task
0 : in loop
1 : start task
1 : end task
1 : in loop
2 : start task
2 : end task
2 : in loop
3 : start task
3 : end task
3 : in loop
4 : start task
4 : end task
4 : in loop
5 : start task
5 : end task
5 : in loop
6 : start task
6 : end task
6 : in loop
7 : start task
7 : end task
7 : in loop
8 : start task
8 : end task
8 : in loop
9 : start task
9 : end task
9 : in loop
LOOP DONE
Time taken: 30.072215795516968
注意:花费的时间几乎与多线程方法相同(略短)。多线程并不能帮助这种工作量
使用多处理的相同代码:
import time
import sys
from multiprocessing import Process, Lock, Value, cpu_count
def cpu_intensive_task(i):
print(i, ' : start task')
count = 10000000 * (i+1)
while count > 0:
count -= 1
print(i, ' : end task')
return i
if __name__ == '__main__':
print("CPU Count: ", cpu_count())
start = time.time()
processes = []
for i in range(10):
p = Process(target=cpu_intensive_task, args=(i,))
processes.append(p)
p.start()
print(i, ' : in loop')
print('LOOP END')
for p in processes:
p.join()
end = time.time()
print('Total Time Taken: ', (end - start))
输出:
CPU Count: 8
0 : in loop
1 : in loop
2 : in loop
3 : in loop
4 : in loop
5 : in loop
6 : in loop
7 : in loop
8 : in loop
9 : in loop
LOOP END
0 : start task
1 : start task
2 : start task
3 : start task
5 : start task
4 : start task
8 : start task
7 : start task
6 : start task
9 : start task
0 : end task
1 : end task
2 : end task
3 : end task
4 : end task
5 : end task
6 : end task
7 : end task
8 : end task
9 : end task
Total Time Taken: 10.335741996765137
注意:多处理仅花费多线程方法所需时间的1/3
CPython解释器用来确保每次只有一个线程执行Python字节码的机制。通过使对象模型(包括关键的内置类型,如dict)隐式地安全地防止并发访问,从而简化了CPython的实现。但是,某些扩展模块(标准的或第三方的)被设计为在执行诸如压缩或散列之类的计算密集型任务时释放GIL。此外,在执行I / O时,始终释放GIL。
多重处理:
multiprocessing是一个程序包,它使用类似于线程模块的API支持生成程序。多处理程序包提供了本地和远程并发性,通过使用子进程而不是线程有效地避开了全局解释器锁。因此,多处理模块允许程序员充分利用给定机器上的多个处理器。
因此,只有多处理才能使用多个处理器,因此才是真正的并发。
您需要在多处理版本代码中使用“锁定”吗?您导入了它,但未在代码中使用它。一旦它被锁定,它可能不会更快?
@marlon,这里没有使用锁。但是,如果两个同时运行的函数要访问正在突变的内存,则需要锁。如果您可以在将工作发送给工作人员之前将其分割,那么您就不需要锁,只要将结果返回给单个收集器即可。
另外,我想指出一个警告,此处使用的多进程方法不是可伸缩解决方案的一个很好的示例。您不应使用无数个进程来处理您的输入(在这种情况下,演示的上限为10个)。您要使用固定工作程序进程池,或者要使用一个信号量,直到运行计数再次下降到最大值以下,该信号量才允许您启动新进程。