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);
参数
参数名 |
类型 |
描述 |
输入/输出 |
|---|---|---|---|
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,表示静态切分策略:平均切 |
输入 |
参数名 |
类型 |
描述 |
|---|---|---|
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数据结构说明具体见下表 |
参数名 |
类型 |
描述 |
|---|---|---|
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所示。
宏 |
描述 |
|---|---|
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 |
参数名 |
类型 |
描述 |
|---|---|---|
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循环。注:以上运行结果以实际为准,上述结果仅供参考。