鲲鹏社区首页
中文
注册
我要评分
文档获取效率
文档正确性
内容完整性
文档易理解
在线提单
论坛求助

kupl_parallel_for

创建parallel for并行循环。

接口定义

int kupl_parallel_for(kupl_parallel_for_desc_t *desc, kupl_pf_func_t func, void *args);

参数

表1 参数定义

参数名

类型

描述

输入/输出

desc

kupl_parallel_for_desc_t *

parallel for循环任务的描述,指向kupl_parallel_for_desc_t结构体的指针,具体见下方kupl_parallel_for_desc_t数据结构表

输入

func

kupl_pf_func_t

parallel for循环任务的函数,该函数必须定义为如下形式:void (*kupl_pf_func_t)(kupl_nd_range_t *nd_range, void *args, int tid, int tnum);其中args为该结构体传入的args参数,nd_range表示经过kupl_parallel_for内部处理后该函数实际执行的循环区域,tid与tnum表示当前函数执行所在线程编号与总线程数

输入

args

void *

func函数需要传入的参数

输入

表2 kupl_parallel_for_desc_t的数据结构定义

参数名

类型

描述

range

kupl_nd_range_t *

parallel for范围,指向kupl_nd_range_t结构体的指针,具体见下方kupl_nd_range_t数据结构表

concurrency

int

for循环任务的并发度

egroup

kupl_egroup_h

执行for循环任务的egroup,即能在哪个egroup中的executor执行器上执行

policy

kupl_loop_policy_type_t

parallel for任务遵循的切分策略,当前可设置为KUPL_LOOP_POLICY_STATIC,表示静态切分策略:平均切

KUPL_LOOP_POLICY_DYNAMIC,表示动态切分策略

表3 kupl_nd_range_t的数据结构定义

参数名

类型

描述

dim

int

parallel for范围的维度,最大值为KUPL_MAX_DIM_SIZE,当前为3

nd_range

kupl_range_t[]

每个维度的具体范围,例如nd_range[0]表示维度0的范围;nd_range数组大小为KUPL_MAX_DIM_SIZE;kupl_range_t数据结构说明具体见下表

表4 kupl_range_t的数据结构定义

参数名

类型

描述

upper

size_t

parallel for循环的结束值,即范围的上限

lower

size_t

parallel for循环的起始值,即范围的下限

step

size_t

parallel for循环的步长,即每次循环增大的值

blocksize

size_t

任务拆分所得块大小所允许的最小值,即影响for循环最终拆分得到的块数

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

表5 kupl_nd_range_t的宏定义

描述

KUPL_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

KUPL_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

KUPL_2D_RANGE_INIT(_range, _row_begin, _row_end, _row_blocksize, _col_begin, _col_end, _col_blocksize)

配置维度为2、步长为1的parallel for范围

具体功能:

将_range的维度设置为2;将(_range).nd_range[0]的上限、下限、块数分别设置为_col_end、_col_begin、_col_blocksize,将步长设置为1;将(_range).nd_range[1]的上限、下限、块数分别设置为_row_end、_row_begin、_row_blocksize,将步长设置为1

KUPL_STRIDE_2D_RANGE_INIT(_range, _row_begin, _row_end, _row_step, _row_blocksize, _col_begin, _col_end, _col_step, _col_blocksize)

配置维度为2的parallel for范围

具体功能:

将_range的维度设置为2;将(_range).nd_range[0]的上限、下限、步长、块数分别设置为_col_end、_col_begin、_col_step、_col_blocksize; 将(_range).nd_range[1]的上限、下限、步长、块数分别设置为_row_end、_row_begin、_row_step、_row_blocksize

KUPL_3D_RANGE_INIT(_range, _page_begin, _page_end, _page_blocksize, _row_begin, _row_end, _row_blocksize, _col_begin, _col_end, _col_blocksize)

配置维度为3、步长为1的parallel for范围

具体功能:

将_range的维度设置为3;将(_range).nd_range[0]的上限、下限、块数分别设置为_col_end、_col_begin、_col_blocksize,将步长设置为1;将(_range).nd_range[1]的上限、下限、块数分别设置为_row_end、_row_begin、_row_blocksize,将步长设置为1; 将(_range).nd_range[2]的上限、下限、块数分别设置为_page_end、_page_begin、_page_blocksize,将步长设置为1

KUPL_STRIDE_3D_RANGE_INIT(_range, _page_begin, _page_end, _page_step, _page_blocksize, _row_begin, _row_end, _row_step, _row_blocksize, _col_begin, _col_end, _col_step, _col_blocksize)

配置维度为3的parallel for范围

具体功能:

将_range的维度设置为3;将(_range).nd_range[0]的上限、下限、步长、块数分别设置为_col_end、_col_begin、_col_step、_col_blocksize; 将(_range).nd_range[1]的上限、下限、步长、块数分别设置为_row_end、_row_begin、_row_step、_row_blocksize; 将(_range).nd_range[2]的上限、下限、步长、块数分别设置为_page_end、_page_begin、_page_step、_page_blocksize

返回值

  • 成功:返回KUPL_OK
  • 失败:返回KUPL_ERROR

示例

一维示例:

#include <stdio.h>
#include <pthread.h>
#include "kupl.h"
static inline void task_int_loop(kupl_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 = kupl_get_num_executors();
    kupl_nd_range_t range;
    KUPL_1D_RANGE_INIT(range, 0, num_threads, 1);
    int executors[num_threads];
    for (int i = 0; i < num_threads; i++) {
        executors[i] = i;
    }
    kupl_egroup_h eg = kupl_egroup_create(executors, num_threads);
    kupl_parallel_for_desc_t desc = {
        .range = &range,
        .concurrency = num_threads,
        .egroup = eg,
        .policy = KUPL_LOOP_POLICY_STATIC
    };
    kupl_parallel_for(&desc, task_int_loop, nullptr);
    kupl_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
三维示例:
#include <stdio.h>
#include <pthread.h>
#include "kupl.h"
static inline void task_int_loop(kupl_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) {
        for (int i = nd_range->nd_range[1].lower; i < nd_range->nd_range[1].upper; i += nd_range->nd_range[1].step) {
            for (int i = nd_range->nd_range[2].lower; i < nd_range->nd_range[2].upper; i += nd_range->nd_range[2].step) {
                printf("pthread %lu: task_int_loop exe\n", pthread_self());
            }
        }
    }
}
int main()
{
    const int num_threads = kupl_get_num_executors();
    kupl_nd_range_t range;

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