Cilk中给线程分配任务,给NUMA节点分配线程
Posted
技术标签:
【中文标题】Cilk中给线程分配任务,给NUMA节点分配线程【英文标题】:Assigning tasks to threads in Cilk and assigning threads to NUMA nodes 【发布时间】:2013-08-25 04:18:55 【问题描述】:例如,有三个线程。
线程 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#
【问题讨论】:
【参考方案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() 的延续。但是由于一个worker随机选择从哪个worker窃取,所以不能保证main()的最后一个延续会在task1_task2_task3()工作之前被窃取。
巴里·坦南鲍姆 英特尔 Cilk 开发
【讨论】:
每个生成的taskX()
对应于task(X)
,task(X)
必须定位自己的数据部分。换句话说,task(X)
必须处理先前在特定 NUMA 节点上分配的 data[X]
。我无法通过__cilkrts_get_worker_number()
(总是返回0)和cilk::current_worker_id()`(无法编译)获得线程ID。同样在 bash 中设置 CILK_NPROC
不会影响 __cilkrts_get_nworkers()
(总是返回 8,我的四核 Intel 系统中的逻辑 CPU 数量)和 __cilkrts_get_total_workers()
(总是返回 23)返回的值。以上是关于Cilk中给线程分配任务,给NUMA节点分配线程的主要内容,如果未能解决你的问题,请参考以下文章
在 linux(CentOS)/多处理器设置中,如何将 CPU 内核分配给 NUMA 节点?