简体   繁体   English

工人完成任务后会发生什么?

[英]What happens with workers when they are done with their task?

I have a task, which I aim to parallelize with the help of the joblib -library.我有一个任务,我的目标是在joblib -library 的帮助下并行化。 The function is fairly slow when ran sequentially, therefore I tried using parallelization paradigms to speed up the process. function 在顺序运行时相当慢,因此我尝试使用并行化范例来加快进程。

with Parallel(n_jobs = -1,verbose = 100) as parallel:
test = parallel(delayed(create_time_series_capacity_v4)(block_info.UnitID[i]) for i in block_info.UnitID.unique()) 
out_data = pd.concat([out_data,test[test.columns[1]]],axis=1 )

The block unique has approximately 1000 entries and the creation of the timeseries, takes longer for some units compared to others.唯一的块有大约 1000 个条目,并且与其他单元相比,某些单元的时间序列的创建需要更长的时间。 Which leaves me to think, that some workers are left working while others are performing an intensive task.这让我想到,一些工人正在工作,而另一些工人正在执行一项繁重的任务。 Is there a way for to reuse the available processes rather than leaving them idling?有没有办法重用可用的进程而不是让它们闲置? I have pasted below what the code returns while being executed:我在下面粘贴了代码在执行时返回的内容:

UNIT05-001 has been written
UNIT04-001 has been written
UNIT05-003 has been written
[Parallel(n_jobs=-1)]: Done   1 tasks      | elapsed:    0.2s
[Parallel(n_jobs=-1)]: Done   2 out of  10 | elapsed:    0.2s remaining:    1.2s
[Parallel(n_jobs=-1)]: Done   3 out of  10 | elapsed:    0.2s remaining:    0.7s
UNIT05-004 has been written
[Parallel(n_jobs=-1)]: Done   4 out of  10 | elapsed:    0.4s remaining:    0.7s
UNIT05-002 has been written
[Parallel(n_jobs=-1)]: Done   5 out of  10 | elapsed:    0.6s remaining:    0.6s
UNIT02-001 has been written
[Parallel(n_jobs=-1)]: Done   6 out of  10 | elapsed:   27.9s remaining:   18.5s
UNIT01-001 has been written
[Parallel(n_jobs=-1)]: Done   7 out of  10 | elapsed:   50.4s remaining:   21.5s

I am not that familiar with joblib but I quickly perused the documentation.我对joblib不是很熟悉,但我很快就阅读了文档。 It appears that you are using the default "multiprocessing" backend that is based on Pythons multiprocessing.Pool implementation, of which I do know a bit.看来您正在使用基于 Python 的multiprocessing.Pool实现的默认“多处理”后端,我确实知道一点。 This class creates a pool of processes as you would expect.这个 class 如您所料创建了一个进程池。 Your 1000 tasks are placed on a "task queue" (see Chunking below).您的 1000 个任务被放置在“任务队列”中(请参阅下面的分块)。 Each process in the pool is initially idle so they each remove a task from the queue and execute their respective tasks.池中的每个进程最初都是空闲的,因此它们每个都从队列中删除一个任务并执行各自的任务。 When a process has completed executing the task, it becomes idle again and so it goes back to retrieve the next task on the queue.当一个进程完成执行任务时,它再次变为空闲状态,因此它返回以检索队列中的下一个任务。 This continues until there are no more tasks on the queue at which point all the processors remain idle until another task is added.这种情况一直持续到队列中没有更多任务为止,此时所有处理器都保持空闲状态,直到添加另一个任务为止。

What we cannot assume in general is that every task takes an equal amount of time to run.我们一般不能假设每个任务都需要相同的时间来运行。 But for the sake of argument let's assume that all tasks take an equal amount of time to execute.但是为了争论,我们假设所有任务都需要相同的时间来执行。 If you submit 1000 tasks to be handled by 16 processors, then after each process has executed 62 tasks (16 * 62 = 992) there will be only 8 tasks left on the task queue to be executed.如果你提交 1000 个任务由 16 个处理器处理,那么每个进程执行完 62 个任务(16 * 62 = 992)后,任务队列中将只剩下 8 个任务要执行。 In this case 8 processes will remain idle while the other 8 processes execute the final 8 tasks.在这种情况下,8 个进程将保持空闲,而其他 8 个进程执行最后的 8 个任务。 But unless these tasks are very long running, you would see all 16 processes going idle and remaining that way more or less at the same time.但是除非这些任务运行时间很长,否则您会看到所有 16 个进程都处于空闲状态,并且或多或少地同时保持这种状态。 Now let us assume that all tasks take the same amount of time except the very last task submitted, which takes 15 minutes longer to execute.现在让我们假设所有任务都花费相同的时间,除了最后提交的任务,它需要多 15 分钟才能执行。 Now you would expect to see 15 processes going idle more or less at the same time with the 16th processor taking an extra 15 minutes before it goes idle.现在,您可能会看到 15 个进程或多或少同时处于空闲状态,而第 16 个处理器在空闲之前需要额外的 15 分钟。 But if this extra long-running task were the first task submitted, again you would expect to see all the processors going and staying idle at the same time.但是,如果这个额外长时间运行的任务是第一个提交的任务,那么您会再次期望看到所有处理器同时运行并保持空闲状态。 Of course, the process that executed the very long-running task will end up processing fewer tasks than the other processes under the assumption that the other tasks take far less time to complete.当然,假设其他任务完成所需的时间要少得多,那么执行非常长时间运行的任务的进程最终将比其他进程处理更少的任务。

Chunking分块

The multiprocessing.Pool suports chunking ; multiprocessing.Pool支持分块 whether or not joblib uses this capaility or not I cannot determine. joblib是否使用此功能我无法确定。 But this is the way it works:但这是它的工作方式:

Since reading and writing to the task queue can be rather expensive, to reduce the number of operations to the task queue the pool can batch the submitted tasks into chunks of a certain size.由于对任务队列的读取和写入可能相当昂贵,为了减少对任务队列的操作数量,池可以将提交的任务批处理成一定大小的 That is, instead of writing 1000 tasks to the queue one at a time, the pool might write the tasks in chunks of 16 tasks as an example of a possible chunk size.也就是说,不是一次将 1000 个任务写入队列,池可能会将任务写入 16 个任务的块中,作为可能的块大小的示例。 Thus, when a processor becomes idle, it gets from the task queue the next chunk containing 16 tasks.因此,当处理器空闲时,它会从任务队列中获取下一个包含 16 个任务的块。 The process will not become idle until all 16 tasks have been executed and only then will the process try to get the next chunk of tasks.在执行完所有 16 个任务之前,该进程不会变为空闲状态,然后该进程才会尝试获取下一个任务块。

So, if a chunk size of 16 were being used, there would be 62 chunks of size 16 (16 * 62 = 992 tasks) placed on the queue plus a final chunk of 8 tasks for a total of 63 chunks.因此,如果使用大小为 16 的块,则将有 62 个大小为 16 的块(16 * 62 = 992 个任务)放置在队列中,再加上最后一个包含 8 个任务的块,总共 63 个块。 After each of the 16 processes has executed 3 chunks (16 * 3 = 48 chunks), there would be 15 chunks left on the queue.在 16 个进程中的每一个都执行了 3 个块(16 * 3 = 48 个块)之后,队列中将剩下 15 个块。 So one of the processes would go idle immediately.因此,其中一个进程将 go 立即空闲。 Of the 15 processors left processing the 15 chunks, remember that one of the chunks only contains 8 tasks rather than 16. This process will go idle before the other 14, each of which will still have 8 more tasks to execute in its final chunk.在剩下的 15 个处理器中处理 15 个块,请记住其中一个块只包含 8 个任务而不是 16 个。这个进程将 go 在其他 14 个之前空闲,每个在其最后一个块中还有 8 个任务要执行。

Conclusion结论

The above examples based on tasks that all take the same time to run is not very realistic but should still give you an idea of how things work.上面基于所有需要相同时间运行的任务的示例不是很现实,但仍然应该让您了解事情是如何工作的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM