OpenMP 绑定核跟线程
- Micro Topics
- 2025-05-29
- 425 Views
- 0 Comments
- 366 Words
for (; i < nthreads; ++i)
{
int err;
start_data->ts.place_partition_off = thr->ts.place_partition_off;
start_data->ts.place_partition_len = thr->ts.place_partition_len;
start_data->place = 0;
if ( (gomp_places_list != NULL, 0))
{
switch (bind)
{
case omp_proc_bind_true:
case omp_proc_bind_close:
if (k == s)
{
++p;
if (p == (team->prev_ts.place_partition_off
+ team->prev_ts.place_partition_len))
p = team->prev_ts.place_partition_off;
k = 1;
if (i == nthreads - rest)
s = 1;
}
else
++k;
break;
case omp_proc_bind_master:
break;
case omp_proc_bind_spread:
if (k == 0)
{
/* T <= P. */
if (p < rest)
p += s + 1;
else
p += s;
if (p == (team->prev_ts.place_partition_off
+ team->prev_ts.place_partition_len))
p = team->prev_ts.place_partition_off;
start_data->ts.place_partition_off = p;
if (p < rest)
start_data->ts.place_partition_len = s + 1;
else
start_data->ts.place_partition_len = s;
}
else
{
/* T > P. */
if (k == s)
{
++p;
if (p == (team->prev_ts.place_partition_off
+ team->prev_ts.place_partition_len))
p = team->prev_ts.place_partition_off;
k = 1;
if (i == nthreads - rest)
s = 1;
}
else
++k;
start_data->ts.place_partition_off = p;
start_data->ts.place_partition_len = 1;
}
break;
}
start_data->place = p + 1;
if (affinity_thr != NULL && pool->threads[i] != NULL)
continue;
gomp_init_thread_affinity (attr, p);
}
这段代码是 gomp_team_start() 中为新线程进行 place 绑定(affinity placement) 的关键部分。它的核心作用是:根据 OpenMP 的 proc_bind 策略,为每个新线程分配合适的 CPU 运行位置(place),并初始化线程亲和性(thread affinity)。
✅ 主要功能概览
对于每个线程 i ∈ [old_threads_used, nthreads):
-
默认继承 place_partition 信息:
start_data->ts.place_partition_off = thr->ts.place_partition_off; start_data->ts.place_partition_len = thr->ts.place_partition_len; start_data->place = 0; -
如果启用了 place 列表(
gomp_places_list != NULL),则根据proc_bind策略重新计算 place 绑定:switch (bind) { case omp_proc_bind_true: case omp_proc_bind_close: case omp_proc_bind_master: case omp_proc_bind_spread: -
计算当前线程应绑定的 place 编号
p,并更新其线程结构体中的place_partition_off/len。 -
最终调用
gomp_init_thread_affinity(attr, p)完成线程 affinity 设置。
🔧 各个 bind 策略解释
| 策略名 | 行为说明 |
|---|---|
omp_proc_bind_master |
所有线程使用与 master 相同的 place,默认不更改 p。 |
omp_proc_bind_true / close |
尽量将线程绑定到紧密相邻的 place,通过 k 和 s 控制周期性换组。 |
omp_proc_bind_spread |
尽量将线程均匀分布到不同 place,尤其在线程数 > place 数时将 place 拆分为单线程。 |
🧠 核心变量含义
| 变量名 | 含义 |
|---|---|
p |
当前 place 编号,表示线程应该被分配的 CPU core group 索引 |
k |
当前在某个 place 上放了几个线程 |
s |
每个 place 应分配多少线程(基本值) |
rest |
多余线程个数,用于在部分 place 上分配 s+1 个线程 |
start_data->place |
最终分配给线程的逻辑编号(place id + 1) |
✅ 特别判断:是否需要创建新线程
if (affinity_thr != NULL && pool->threads[i] != NULL)
continue;
如果 affinity 线程池中已经有复用线程,就跳过 pthread_create,表示线程池线程可被复用,不需要新建。
🔚 总结一句话
这一段代码的主要作用是:根据不同的
proc_bind策略计算每个线程应绑定的 CPU place,并调用亲和性设置函数实现线程绑定,从而实现 OpenMP 的线程拓扑感知调度。
