我正在尝试使用python multiprocessing 模块来减少过滤代码的时间。一开始我做了一些实验。结果并不乐观。
我已经定义了一个在一定范围内运行循环的函数。然后,在有和没有线程的情况下运行此函数,并测量时间。这是我的代码:
import time
from multiprocessing.pool import ThreadPool
def do_loop(i,j):
l = []
for i in range(i,j):
l.append(i)
return l
#loop veriable
x = 7
#without thredding
start_time = time.time()
c = do_loop(0,10**x)
print("--- %s seconds ---" % (time.time() - start_time))
#with thredding
def thread_work(n):
#dividing loop size
a = 0
b = int(n/2)
c = int(n/2)
#multiprocessing
pool = ThreadPool(processes=10)
async_result1 = pool.apply_async(do_loop, (a,b))
async_result2 = pool.apply_async(do_loop, (b,c))
async_result3 = pool.apply_async(do_loop, (c,n))
#get the result from all processes]
result = async_result1.get() + async_result2.get() + async_result3.get()
return result
start_time = time.time()
ll = thread_work(10**x)
print("--- %s seconds ---" % (time.time() - start_time))
对于x = 7,结果为:
--- 1.0931916236877441 seconds ---
--- 1.4213247299194336 seconds ---
不使用线程即可花费更少的时间。这是另一个问题。对于X = 8,大多数时候我会得到 MemoryError 进行线程化。一旦获得此结果:
--- 17.04124426841736 seconds ---
--- 32.871358156204224 seconds ---
该解决方案非常重要,因为我需要优化一个耗时6个小时的filtering task。
答案 0 :(得分:2)
这里的任务是如此之小,以至于并行化开销极大地控制了收益。这是常见的常见问题解答。
答案 1 :(得分:1)
为什么对线程使用多处理?
最好是创建多个线程实例。给他们每个人的任务。最后,开始所有这些。等到他们完成。同时,将结果收集到一些列表中。
根据我的经验(对于一个特定任务),我发现即使在开始时创建一个完整的线程图也比在图的下一个节点中开始任务之前直接花费更少的开销。我的意思是10、100、1000、10000个线程。只需确保线程在空闲时间(即time.sleep(0.5)
)处于休眠状态,以避免浪费CPU周期。
对于线程,您可以使用线程安全的列表,字典和队列。
答案 2 :(得分:1)
最好使用multiprocessing.Process(),因为python具有Global Interpreter Lock(GIL)。因此,即使您创建线程来提高任务速度,也不会增加线程数量,它会一步一步地完成。您可以参考python文档获取有关GIL和线程的信息。
答案 3 :(得分:1)
Aroosh Rana可能是最好的答案,但是在使用该方法进行测试时,需要注意一些事项。在循环中增长数组的方式可能效率很低,请考虑预先分配其完整大小。另外,仔细查看划分工作的方式,有两个循环处理数组的一半,一个循环从n / 2到n / 2。另外,正如在其他地方提到的,“完成”一词相当琐碎,不会从并行处理中受益。 我已经尝试过改进您以前的测试。
scipy.misc.toimage(output * 255, high=255, low=0, cmin=0, cmax=255).save(
params.result_dir + 'final/%5d_00_%d_out.png' % (test_id, ratio))
还要记住,使用这种方法,您不必在最后合并结果,因为每个线程将在同一数组上进行处理。
答案 4 :(得分:1)
根据您的任务,多处理可能会或可能不会花费更长的时间。 如果您想利用CPU内核的优势并加快过滤过程,则应该use multiprocessing.Pool
提供了一种并行执行函数的简便方法 跨多个输入值,跨多个分布输入数据 进程(数据并行性)。
我一直在创建数据过滤的示例,然后一直在测量简单方法的时机和多进程方法的时机。 (从您的代码开始)
# take only the sentences that ends in "we are what we dream", the second word is "are"
import time
from multiprocessing.pool import Pool
LEN_FILTER_SENTENCE = len('we are what we dream')
num_process = 10
def do_loop(sentences):
l = []
for sentence in sentences:
if sentence[-LEN_FILTER_SENTENCE:].lower() =='we are what we doing' and sentence.split()[1] == 'are':
l.append(sentence)
return l
#with thredding
def thread_work(sentences):
#multiprocessing
pool = Pool(processes=num_process)
pool_food = (sentences[i: i + num_process] for i in range(0, len(sentences), num_process))
result = pool.map(do_loop, pool_food)
return result
def test(data_size=5, sentence_size=100):
to_be_filtered = ['we are what we doing'*sentence_size] * 10 ** data_size + ['we are what we dream'*sentence_size] * 10 ** data_size
start_time = time.time()
c = do_loop(to_be_filtered)
simple_time = (time.time() - start_time)
start_time = time.time()
ll = [e for l in thread_work(to_be_filtered) for e in l]
multiprocessing_time = (time.time() - start_time)
assert c == ll
return simple_time, multiprocessing_time
data_size表示数据的长度,句子_size是每个数据元素的乘数,您可以看到句子_size与从数据中为每个项目请求的CPU操作数成正比。
data_size = [1, 2, 3, 4, 5, 6]
results = {i: {'simple_time': [], 'multiprocessing_time': []} for i in data_size}
sentence_size = list(range(1, 500, 100))
for size in data_size:
for s_size in sentence_size:
simple_time, multiprocessing_time = test(size, s_size)
results[size]['simple_time'].append(simple_time)
results[size]['multiprocessing_time'].append(multiprocessing_time)
import pandas as pd
df_small_data = pd.DataFrame({'simple_data_size_1': results[1]['simple_time'],
'simple_data_size_2': results[2]['simple_time'],
'simple_data_size_3': results[3]['simple_time'],
'multiprocessing_data_size_1': results[1]['multiprocessing_time'],
'multiprocessing_data_size_2': results[2]['multiprocessing_time'],
'multiprocessing_data_size_3': results[3]['multiprocessing_time'],
'sentence_size': sentence_size})
df_big_data = pd.DataFrame({'simple_data_size_4': results[4]['simple_time'],
'simple_data_size_5': results[5]['simple_time'],
'simple_data_size_6': results[6]['simple_time'],
'multiprocessing_data_size_4': results[4]['multiprocessing_time'],
'multiprocessing_data_size_5': results[5]['multiprocessing_time'],
'multiprocessing_data_size_6': results[6]['multiprocessing_time'],
'sentence_size': sentence_size})
绘制小数据的计时:
ax = df_small_data.set_index('sentence_size').plot(figsize=(20, 10), title = 'Simple vs multiprocessing approach for small data')
ax.set_ylabel('Time in seconds')
如您所见,当您拥有大数据且每个数据元素需要相对大量的CPU能力时,多处理能力正在发挥作用。