大家好,今天小白给大家简单分享下Hetcompute sdk中task相关的基础知识,欢迎一起交流学习。
一、Hetcompute sdk中的kernel
HetCompute任务包含可在系统中的任何设备上执行的工作:CPU,GPU或Qualcomm Hexagon DSP。 这使得HetCompute程序员可以编写由各种任务组成的应用程序,充分利用现代计算系统中可用的异构设备的性能和功效。
HetCompute任务使用内核来实现这种计算异构性。 内核包含计算,即实际的设备代码,任务执行。 这可能是CPU代码,GPU代码或Qualcomm Hexagon DSP代码,导致三种不同类型的内核。 在当前的HetCompute版本中,每个任务只包含一个内核,指示此任务在哪个设备上执行。
二、如何创建kernels
目前,HetCompute中有三种类型的内核。 使用以下方法创建每一种内核:
1、创建CPU kernel
要创建CPU内核,使用hetcompute :: create_cpu_kernel,它需要函数或函数对象(即lambda表达式或仿函数)。
2、创建GPU kernel
要创建GPU内核,使用hetcompute :: create_gpu_kernel,这里有两种:一个用于包装OpenCL C内核,另外一个用于OpenGL ES计算着色器。
OpenCL变体的参数是:
a、包含OpenCL GPU设备函数源的字符串;
b、包含设备函数名称的字符串
OpenGL变量将包含计算着色器程序源的字符串作为参数;
3、创建DSP kernel
要创建DSP内核,请使用hetcompute :: create_dsp_kernel。 它需要兼容DSP的C功能
4、使用以上API创建三种kernel
#include <hetcompute/hetcompute.hh>
static int f1(int x) {
return x * 2;
}static auto f2 = [](int x) -> int { return x * 2; };
static struct
{
int operator()(int x) { return x * 2; }
} f3;// Source string for an OpenCL C kernel
static std::string const f4_string = "__kernel void f4(__global int *x, __global int *y) {"
" int i = get_global_id(0);"
" y[i] = x[i];"
"}";static int f5(int* x, int* y, int l)
{
int i = 0;
for (i = 0; i < l; i++)
y[i] = x[i] * 2;
return 0;
}
int main()
{
hetcompute::runtime::init(); // Create a cpu_kernel from a function
auto k1 = hetcompute::create_cpu_kernel(f1); // Create a cpu_kernel from a lambda expression
auto k2 = hetcompute::create_cpu_kernel(f2); // Create a cpu_kernel from a functor
auto k3 = hetcompute::create_cpu_kernel(f3); // Create a gpu_kernel from an OpenCL C GPU function
auto k4 = hetcompute::create_gpu_kernel<hetcompute::buffer_ptr<int>, hetcompute::buffer_ptr<int>>(f4_string, "f4"); // Create a hexagon_kernel from a DSP function
auto k5 = hetcompute::create_dsp_kernel<>(f5);
hetcompute::runtime::shutdown();
return 0;
}
创建内核后,hetcompute :: create_task可以使用它来创建任务。 此外,内核可用于创建多个独立任务。
以上展示了从OpenCL C GPU函数创建gpu_kernel,下面介绍使用OpenGL ES创建GPU kernel
#include <hetcompute/hetcompute.hh>
#define LOCAL_SIZE 16 // This should match the local_size_x value in the shader
const char* shader_code = R"GLCODE(
#version 310 es
precision highp float;
layout(local_size_x = 16) in;
layout(std430) buffer;
layout(binding = 2) writeonly buffer Output {
float elements[];
} output_data;
layout(binding = 0) readonly buffer Input0 {
float elements[];
} input_data0;layout(binding = 1) readonly buffer Input1 {
float elements[];
} input_data1;
void main()
{
uint ident = gl_GlobalInvocationID.x;
output_data.elements[ident] = input_data0.elements[ident] + input_data1.elements[ident];
}
)GLCODE";int main()
{
hetcompute::runtime::init();
auto buf_a = hetcompute::create_buffer<float>(1024);
auto buf_b = hetcompute::create_buffer<float>(buf_a.size());buf_a.acquire_wi();
buf_b.acquire_wi();
// Initialize the input vectors
for (size_t i = 0; i < buf_a.size(); ++i)
{
buf_a[i] = i;
buf_b[i] = buf_a.size() - i;
}
buf_a.release();
buf_b.release();
auto buf_c = hetcompute::create_buffer<float>(buf_a.size());
auto gl_vadd = hetcompute::beta::create_gpu_kernel<hetcompute::in<hetcompute::buffer_ptr<float>>,
hetcompute::in<hetcompute::buffer_ptr<float>>,
hetcompute::out<hetcompute::buffer_ptr<float>>>(
hetcompute::beta::gl, shader_code);
hetcompute::range<1> global_range(buf_a.size());
hetcompute::range<1> local_range(LOCAL_SIZE);
// Create a task
auto gpu_task = hetcompute::create_task(gl_vadd, // gpu kernelglobal_range, // global range
local_range, // local range
buf_a, //
parameters // rest correspond to gpu_vadd template parameters
buf_b,
buf_c); gpu_task->launch();
gpu_task->wait_for();
hetcompute::runtime::shutdown();
}相应地,当传递OpenCL C函数时,用户可以选择通过
hetcompute :: beta :: cl使OpenCL显式,如下图所示。
auto k4 = hetcompute :: beta :: create_gpu_kernel <hetcompute :: buffer_ptr <int>,hetcompute::buffer_ptr<INT>>(hetcompute :: beta :: cl,f4_string,“f4”);三、设置kernel属性
从CPU、GPU、DSP函数创建任务之后,Qualcomm HetCompute用户无法将内部函数替换为内核中的另一个函数。 但是,用户可以更改内核的以下属性:
1、阻塞(blocking):表示是否希望从此内核生成的CPU任务阻止外部事件(如I / O活动(阻塞任务))。 可以使用内核对象的set_blocking和is_blocking方法设置和查询blocking属性。
2、Big:如在需要大量计算的场合下将负载放到大核上以提高效率,当负载较小时可以关闭大核,将任务放到小核上运行以降低功耗。使用内核对象的set_big和is_big方法设置和查询big属性;(使用set_little和is_little设置和查询little)
3、用法示例
#include <hetcompute/hetcompute.hh>
int
main()
{
hetcompute::runtime::init(); auto k1 = hetcompute::create_cpu_kernel([] { HETCOMPUTE_ILOG("big task
executed"); }); // inform the Hetcompute runtime that the kernel is best executed on a big
// core in a big.LITTLE SoC
k1.set_big();
auto t1 = hetcompute::launch(k1);
t1->wait_for(); auto k2 = hetcompute::create_cpu_kernel([] { HETCOMPUTE_ILOG("LITTLE task
executed"); }); // inform the Hetcompute runtime that the kernel is best executed on a
// LITTLE core in a big.LITTLE SoC
k2.set_little();
auto t2 = hetcompute::launch(k2);
t2->wait_for(); hetcompute::runtime::shutdown();
return 0; }
四、总结
本篇主要是简单介绍了如何创建CPU、GPU、DSP kernel以及设置属性,欢迎一起交流学习。