有些任务从文件中读取,执行某些处理并写入文件。这些任务将根据依赖性进行调度。此外,任务可以并行运行,因此需要优化算法以串行运行相关任务,并尽可能并行运行。
例如:
因此,运行此方法的一种方法就是运行 1,2和& 4并行。其次是3。
另一种方式可能是 运行1然后运行2,3& 4并行。
另一个可以串行运行1和3,并行运行2和4。
有什么想法吗?
答案 0 :(得分:11)
让每个任务(例如A,B,...
)成为directed acyclic graph中的节点,并根据您的1,2,...
定义节点之间的弧。
然后,您可以topologically order使用图表(或使用基于搜索的方法,如BFS)。在您的示例中,C<-A->B->D
和E->F
因此A
&amp; E
的深度为0,需要先运行。然后,您可以并行运行F
,B
和C
,然后D
。
另外,请查看PERT。
您如何知道B
的优先级是否高于F
?
这是用于查找排序的拓扑排序背后的直觉。
它首先找到根(没有传入边)节点(因为DAG中必须存在一个)。在你的情况下,那是A
&amp; E
。这解决了需要完成的第一轮工作。接下来,需要完成根节点(B
,C
和F
)的子节点。通过查询图表可以轻松获得此信息。然后重复该过程,直到找不到(完成)节点(作业)。
答案 1 :(得分:7)
给定项目之间的映射以及它们所依赖的项目,拓扑排序会对项目进行排序,以使项目不在其所依赖的项目之前。
This Rosetta code task有solution in Python,可以告诉您哪些项目可以并行处理。
根据您的输入,代码变为:
try:
from functools import reduce
except:
pass
data = { # From: http://stackoverflow.com/questions/18314250/optimized-algorithm-to-schedule-tasks-with-dependency
# This <- This (Reverse of how shown in question)
'B': set(['A']),
'C': set(['A']),
'D': set(['B']),
'F': set(['E']),
}
def toposort2(data):
for k, v in data.items():
v.discard(k) # Ignore self dependencies
extra_items_in_deps = reduce(set.union, data.values()) - set(data.keys())
data.update({item:set() for item in extra_items_in_deps})
while True:
ordered = set(item for item,dep in data.items() if not dep)
if not ordered:
break
yield ' '.join(sorted(ordered))
data = {item: (dep - ordered) for item,dep in data.items()
if item not in ordered}
assert not data, "A cyclic dependency exists amongst %r" % data
print ('\n'.join( toposort2(data) ))
然后生成此输出:
A E
B C F
D
输出的一行上的项目可以按任何子顺序处理,或者实际上并行处理;只要更高行的所有项都在后续行的项之前处理以保留依赖项。
答案 2 :(得分:1)
你的任务是一个定向图,(希望)没有周期。
我包含sources
和wells
(来源是不依赖的任务(没有入站边缘),井是没有任务解锁的任务(没有出站边缘))。
一个简单的解决方案是根据其有用性优先处理您的任务(让我们称之为U
。
通常,从井开始,它们具有实用性U = 1
,因为我们希望它们完成。
将所有井的前任放入当前正在评估的节点的列表L
中。
然后,取L
中的每个节点,它的U
值是取决于他的节点的U
值的总和+ 1.放置当前节点的所有父节点在L
列表中。
循环,直到所有节点都被处理完毕。
然后,启动可以启动且具有最大U
值的任务,因为它将解锁最大数量的任务。
在您的示例中,
U(C) = U(D) = U(F) = 1
U(B) = U(E) = 2
U(A) = 4
意思是你将首先用E开始,然后是B和C(如果可能的话),然后是D和F
答案 3 :(得分:1)
首先生成任务的拓扑排序。检查此阶段的周期。此后,您可以通过查看最大的反链来利用并行性。粗略地说,这些是任务集,它们的元素之间没有依赖关系。
从理论角度来看,this paper涵盖了该主题。
答案 4 :(得分:0)
不考虑问题的串行/并行方面,此代码至少可以确定整个串行解决方案:
def order_tasks(num_tasks, task_pair_list):
task_deps= []
#initialize the list
for i in range(0, num_tasks):
task_deps[i] = {}
#store the dependencies
for pair in task_pair_list:
task = pair.task
dep = pair.dependency
task_deps[task].update({dep:1})
#loop through list to determine order
while(len(task_pair_list) > 0):
delete_task = None
#find a task with no dependencies
for task in task_deps:
if len(task_deps[task]) == 0:
delete_task = task
print task
task_deps.pop(task)
break
if delete_task == None:
return -1
#check each task's hash of dependencies for delete_task
for task in task_deps:
if delete_key in task_deps[task]:
del task_deps[task][delete_key]
return 0
如果更新循环以检查完全满足的依赖关系以遍历整个列表并执行/删除不再具有任何依赖关系的任务,那么这也应该允许您利用完成并行的任务。