0

例如,有三个线程。

  • 线程 1 被分配了任务 1、2 和 3。
  • 线程 2 被分配了任务 4、5 和 6。
  • 线程 3 被分配了任务 7、8 和 9。

任务规模不统一。分配给一个线程的任务具有非常相似的工作集,因此当这三个任务都由同一个线程执行时,缓存将得到有效利用。我还应该注意,这些任务将在具有四个节点的 NUMA 系统上运行。四个线程中的每一个都必须分配给系统的一个节点。

我的问题是关于负载平衡。例如,如果线程 1 在其他任务之前完成其任务并且任务 9 未启动,我希望 Cilk 调度程序将任务 9 分配给线程 1。

欢迎所有解决方案,包括 Cilk Plus、OpenMP 或网络上免费提供的其他调度程序。

更新:线程必须分配给 NUMA 系统的节点,并且这些线程使用的内存位置必须分配在特定节点上。我已经成功地使用libnuma了 OpenMP。但是,我无法找到如何使用 Cilk、TBB 等将线程映射到节点。如果可以在 Cilk Plus 中获取生成的工作线程 id,我会使用numa_run_on_node(nodeid).

有关 NUMA 架构上 Cilk 可扩展性问题的更多信息:http ://www.sciencedirect.com/science/article/pii/S0167739X03001845#

4

1 回答 1

1

在 Cilk 中执行此操作的正确方法是:

void task1_task2_task3()
{
    cilk_spawn task1();
    cilk_spawn task2();
    task3();
}

void task4_task5_task6()
{
    cilk_spawn task4();
    cilk_spawn task5();
    task6();
}

void task7_task8_task9()
{
    cilk_spawn task7();
    cilk_spawn task8();
    task8();
}

int main()
{
    cilk_spawn task1_task2_task3();
    cilk_spawn task4_task5_task6();
    task7_task8_task9();
    cilk_sync;
    finalize_stuff();
    return 0;
}

请记住,cilk_spawn 是对调度程序的建议,即 cilk_spawn 之后的代码可以被窃取,而不是要求。当一个 cilk_spawn 被执行时,它会在 worker 的双端队列尾部推送一个符号,表明该延续可用于窃取。窃贼总是从双端队列的头部窃取,所以你可以保证一些工作人员会在他们窃取 task1_task2_task3() 的延续之前窃取 main() 的延续。但是由于一个工作人员随机选择从哪个工作人员那里窃取,因此无法保证 main() 的最终延续会在 task1_task2_task3() 工作之前被窃取。

Barry Tannenbaum
英特尔 Cilk 开发

于 2013-08-26T00:18:07.733 回答