有一个图,其中顶点表示代码段,边表示它们之间的依赖关系。此外,每个顶点都有两个数字:相应的代码段可以使用多少个线程(1、2,...或“与内核一样多”),以及估计获得多少时间。那么多线程(与其他线程相比,例如1、0.1或10)。想法是并行运行代码片段,以考虑其依赖性,从而为它们提供这样的线程数,以使总执行时间最小。
是否有一些现有的算法可以做到这一点或可以用作基础?
到目前为止,我的想法如下。例如,我们共有8个线程(因此NT = 8T)和下图。
+----------------+ +----------------+
+-+ A: 0.2x, 1T +----+ | F: 0.1x, 1T |
| +---+------------+ | +---+------------+
| | | |
| +---v------------+ | +---v------------+
| | B: 0.1x, 2T +-+ | | G: 0.3x, NT +-+
| +----------------+ | | +----------------+ |
| | | |
| +----------------+ | | +----------------+ |
+-> C: 0.4x, 1T | | +----> H: 0.1x, 1T | |
+--+-------------+ | +--+-------------+ |
+----+ | | |
| +----------------+ | +--v-------------+ |
| | D: 0.1x, 1T <-+ | J: 1.5x, 4T <-+
| +--+-------------+ +-------+--------+
| | |
| +--v-------------+ |
+-> E: 1.0x, 4T +------------+ |
+----------------+ | |
+--v----v--------+
+ I: 0.01x, 1T |
+----------------+
在任务I中,我们有2个依赖项,E和J。作为J依赖项,我们有F-G和A-H。对于E,A-C和A-B-D。要达到J,我们在A-H上需要0.3倍,在F-G上需要0.4倍,但是G需要很多线程。我们可以首先并行运行A和F(每个都有一个线程)。然后,我们将使用7个线程运行G,而当A完成时,将使用1个线程运行H。但是,还有E分支。理想情况下,我们希望它比J早0.5就绪。在这种情况下,这很容易,因为已经使用一个线程处理了A时,到E的最长路径使用一个线程占用0.4,而另一个路径占用的路径少于这个并且仅使用2个线程-因此我们可以在J运行时运行这些计算。但是,如果说D花费了0.6倍,我们可能还需要与G并行运行。
所以我想我可以从水槽顶点开始,平衡它所依赖的子图的权重。但是,鉴于这些“ N线程”任务,如何执行尚不十分清楚。考虑到x数只是估计值,如果特定任务花费的时间比预期的长或短,则可以进行调整将是很好的。
答案 0 :(得分:2)
您可以将此问题建模为job shop scheduling problem(特别是灵活的作业车间问题,其中机器是处理器,而作业是要运行的程序的一部分)。
首先,您必须稍微修改一下DAG,才能将其转换为另一个代表问题的disjunctive graph DAG。
这种转换非常简单。对于表示作业i, t, nb_t
的任何节点i
,需要1个线程执行t
秒,并且可以并行化为nb_t
个线程,请执行以下操作: br />
将i, t, nb_t
替换为nb_t
顶点i_1, t/nb_t
,...,i_(nb_t), t/nb_t
。对于节点i
的每个传入/传出边缘,从/到所有新创建的节点创建传入/传出边缘。基本上,我们只是将每个可以并行化的作业拆分为可以同时由多个处理器(机器)处理的较小作业。
然后,您将获得析取图,这是车间问题的输入。
然后,您需要做的就是解决这个众所周知的问题,有不同的选择....
我会建议使用MILP求解器,但是从我刚才做的小搜索看来,似乎许多元启发式算法都可以解决该问题(模拟退火,遗传编程等)。