---
title: kpccl_parallel_for
description: "创建parallel for并行循环。"
url: https://www.hikunpeng.com/document/detail/zh/hpchistory/hpckit/develop2400/KunoengHPCKit_developer_029.html
sourcePath: /source/zh/hpchistory/hpckit/develop2400/KunoengHPCKit_developer_029.html
indexId: f801536c0c969f503c41d39dd0ce001f651a384ed38b3fa31f7c59efc79425d673
---
# kpccl_parallel_for

创建parallel for并行循环。

#### 接口定义

int kpccl_parallel_for(kpccl_ND_range_t *range, kpccl_parallel_for_desc_t *desc, kpccl_pf_policy_type_t policy);


#### 参数


**表1 参数定义**

| 参数名 | 类型 | 描述 | 输入/输出 |
| --- | --- | --- | --- |
| range | kpccl\_ND\_range\_t \* | parallel for范围，指向kpccl\_ND\_range\_t结构体的指针，具体见下方kpccl\_ND\_range\_t数据结构表 | 输入 |
| desc | kpccl\_parallel\_for\_desc\_t \* | parallel for循环任务的描述，指向kpccl\_parallel\_for\_desc\_t结构体的指针，具体见下方kpccl\_parallel\_for\_desc\_t数据结构表 | 输入 |
| policy | kpccl\_pf\_policy\_type\_t | parallel for任务遵循的切分策略，当前可设置为KPCCL\_PARALLEL\_FOR\_POLICY\_STATIC，表示静态切分策略：平均切 | 输入 |


**表2 kpccl_ND_range_t的数据结构定义**

| 参数名 | 类型 | 描述 |
| --- | --- | --- |
| dim | int | parallel for范围的维度，最大值为KPCCL\_MAX\_DIM\_SIZE，当前为3 |
| nd\_range | kpccl\_range\_t[] | 每个维度的具体范围，例如nd\_range[0]表示维度0的范围；nd\_range数组大小为KPCCL\_MAX\_DIM\_SIZE；kpccl\_range\_t数据结构说明具体见下表 |


**表3 kpccl_range_t的数据结构定义**

| 参数名 | 类型 | 描述 |
| --- | --- | --- |
| upper | int | parallel for循环的结束值，即范围的上限 |
| lower | int | parallel for循环的起始值，即范围的下限 |
| step | int | parallel for循环的步长，即每次循环增大的值 |
| blocksize | int | 任务拆分所得块大小所允许的最小值，即影响for循环最终拆分得到的块数 |


由于kpccl_ND_range_t的数据结构较为复杂，因此在允许用户自行配置数据结构的同时，也提供了相应的宏，以供用户便捷地配置维度为1的kpccl_ND_range_t。具体的宏如表4所示。


**表4 kpccl_ND_range_t的宏定义**

| 宏 | 描述 |
| --- | --- |
| KPCCL\_1D\_RANGE\_INIT(\_range, \_col\_begin, \_col\_end, \_col\_blocksize) | 配置维度为1、步长为1的parallel for范围 具体功能： 将\_range的维度设置为1；将(\_range).nd\_range[0]的上限、下限、块数分别设置为\_col\_end、\_col\_begin、\_col\_blocksize，将步长设置为1 |
| KPCCL\_STRIDE\_1D\_RANGE\_INIT(\_range, \_col\_begin, \_col\_end, \_col\_step, \_col\_blocksize) | 配置维度为1的parallel for范围 具体功能： 将\_range的维度设置为1；将(\_range).nd\_range[0]的上限、下限、步长、块数分别设置为\_col\_end、\_col\_begin、\_col\_step、\_col\_blocksize |


**表5 kpccl_parallel_for_desc_t的数据结构定义**

| 参数名 | 类型 | 描述 |
| --- | --- | --- |
| func | kpccl\_taskloop\_func\_t | for循环任务的函数，该函数必须定义为如下形式：void (\*kpccl\_taskloop\_func\_t)(kpccl\_ND\_range\_t \*nd\_range, void \*args, int tid, int tnum)；其中args为该结构体传入的args参数，nd\_range表示经过kpccl\_parallel\_for内部处理后该函数实际执行的循环区域，tid与tnum表示当前函数执行所在线程编号与总线程数 |
| args | void \* | func函数需要传入的参数 |
| num\_threads | int | for循环任务的线程数，即并发数 |
| group | kpccl\_egroup\_h | 执行for循环任务的egroup，即能在哪个egroup中的executor执行器上执行 |


#### 返回值

- 成功：返回KPCCL_OK
- 失败：返回KPCCL_ERROR


#### 示例

```
#include <stdio.h>
#include <pthread.h>
#include <omp.h>
#include "kpccl.h"
static inline void task_int_loop(kpccl_ND_range_t *nd_range, void *args, int tid, int tnum)
{
for (int i = nd_range->nd_range[0].lower; i < nd_range->nd_range[0].upper; i += nd_range->nd_range[0].step) {
printf("pthread %lu: task_int_loop exe\n", pthread_self());
}
}
int main()
{
const int num_threads = kpccl_get_num_executors();
kpccl_ND_range_t range;
KPCCL_1D_RANGE_INIT(range, 0, num_threads, 1);
int executors[num_threads];
for (int i = 0; i < num_threads; i++) {
executors[i] = i;
}
kpccl_egroup_h eg = kpccl_egroup_create(executors, num_threads);
#pragma omp parallel num_threads(num_threads)
{
int tid = omp_get_thread_num();
if (tid == 0) {
kpccl_parallel_for_desc_t desc = {
.func = task_int_loop,
.args = nullptr,
.num_threads = num_threads,
.group = eg
};
kpccl_parallel_for(&range, &desc, KPCCL_PARALLEL_FOR_POLICY_STATIC);
}
kpccl_egroup_barrier(eg);
}
kpccl_egroup_destroy(eg);
}
```

运行结果如下。

```
pthread 70369394977328: task_int_loop exe
pthread 70369605054880: task_int_loop exe
pthread 70369596600736: task_int_loop exe
pthread 70369588146592: task_int_loop exe
```

上述示例演示了kpccl执行parallel for循环任务的流程。上述示例中，首先通过KPCCL_1D_RANGE_INIT宏配置了parallel for范围，定义了1维的step步长和block大小都为1，范围从0到num_threads的for循环描述；其次配置了parallel for任务描述，任务的函数为task_int_loop，参数为空，并发度为执行器数量、使用所有执行器；最终通过kpccl_parallel_for函数执行for循环。注：以上运行结果以实际为准，上述结果仅供参考。
