查看: 2167|回复: 0

[分享] imx6q使用openCL

[复制链接]
  • TA的每日心情
    开心
    2024-3-26 15:16
  • 签到天数: 266 天

    [LV.8]以坛为家I

    3299

    主题

    6546

    帖子

    0

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    32024
    最后登录
    2024-4-25
    发表于 2020-5-12 15:29:10 | 显示全部楼层 |阅读模式
    imx6q使用openCL


    imx6上有一个vivante gpu,通过gpu来加速浮点计算效果要好很多,但是通过学习过程中发现,这方面的资料少之又少,通过几天的折腾也算是能跑起来了,所以做一个记录。


    下载openCL库
    在使用openCL之前我们需要先安装openCL库,这些在nxp官网上提供了头文件和.so文件,我们直接下载放到编译器内即可。openCL库路径为:请点击我查了很多资料说只支持openCL1.1,我使用的是gpu-viv-bin-mx6q-1.1.0/ ,可以编译运行,别的版本没有试过。


    安装openCL库
    将下载的usr目录下lib目录和include目录下的文件分别放到编译器目录下的lib和include目录下即可,opt目录下有测试程序可以测试gpu是否正常运行。


    编译openCL程序
    测试程序在文章最后。编译命令为
    arm-fsl-linux-gnueabi-g++ test.cpp -o test -lGAL -lOpenCL
    编译过程中发现需要加-lGAL选项,不然编译报错,至于这个是干嘛的,为什么,没弄明白,如果你知道可以告诉我!


    运行openCL程序
    将可执行程序和.cl程序放到开发板直接运行即可。


    测试程序:(忘记程序抄了哪的了,如有冒犯请告知)
    (1)主程序test.cpp
    1. <font size="3" face="微软雅黑">#include <iostream>
    2. #include <fstream>
    3. #include <sstream>
    4. #include <CL/cl.h>

    5. const int ARRAY_SIZE = 1000;

    6. //一、 选择OpenCL平台并创建一个上下文
    7. cl_context CreateContext()
    8. {
    9.         cl_int errNum;
    10.         cl_uint numPlatforms;
    11.         cl_platform_id firstPlatformId;
    12.         cl_context context = NULL;

    13.         //选择可用的平台中的第一个
    14.         errNum = clGetPlatformIDs(1, &firstPlatformId, &numPlatforms);
    15.         if (errNum != CL_SUCCESS || numPlatforms <= 0)
    16.         {
    17.                 std::cerr << "Failed to find any OpenCL platforms." << std::endl;
    18.                 return NULL;
    19.         }

    20.         //创建一个OpenCL上下文环境
    21.         cl_context_properties contextProperties[] =
    22.         {
    23.                 CL_CONTEXT_PLATFORM,
    24.                 (cl_context_properties)firstPlatformId,
    25.                 0
    26.         };
    27.         context = clCreateContextFromType(contextProperties, CL_DEVICE_TYPE_GPU,
    28.                 NULL, NULL, &errNum);

    29.         return context;
    30. }


    31. //二、 创建设备并创建命令队列
    32. cl_command_queue CreateCommandQueue(cl_context context, cl_device_id *device)
    33. {
    34.         cl_int errNum;
    35.         cl_device_id *devices;
    36.         cl_command_queue commandQueue = NULL;
    37.         size_t deviceBufferSize = -1;

    38.         // 获取设备缓冲区大小
    39.         errNum = clGetContextInfo(context, CL_CONTEXT_DEVICES, 0, NULL, &deviceBufferSize);

    40.         if (deviceBufferSize <= 0)
    41.         {
    42.                 std::cerr << "No devices available.";
    43.                 return NULL;
    44.         }

    45.         // 为设备分配缓存空间
    46.         devices = new cl_device_id[deviceBufferSize / sizeof(cl_device_id)];
    47.         errNum = clGetContextInfo(context, CL_CONTEXT_DEVICES, deviceBufferSize, devices, NULL);

    48.         //选取可用设备中的第一个
    49.         commandQueue = clCreateCommandQueue(context, devices[0], 0, NULL);

    50.         *device = devices[0];
    51.         delete[] devices;
    52.         return commandQueue;
    53. }


    54. // 三、创建和构建程序对象
    55. cl_program CreateProgram(cl_context context, cl_device_id device, const char* fileName)
    56. {
    57.         cl_int errNum;
    58.         cl_program program;

    59.         std::ifstream kernelFile(fileName, std::ios::in);
    60.         if (!kernelFile.is_open())
    61.         {
    62.                 std::cerr << "Failed to open file for reading: " << fileName << std::endl;
    63.                 return NULL;
    64.         }

    65.         std::ostringstream oss;
    66.         oss << kernelFile.rdbuf();

    67.         std::string srcStdStr = oss.str();
    68.         const char *srcStr = srcStdStr.c_str();
    69.         program = clCreateProgramWithSource(context, 1,
    70.                 (const char**)&srcStr,
    71.                 NULL, NULL);

    72.         errNum = clBuildProgram(program, 0, NULL, NULL, NULL, NULL);

    73.         return program;
    74. }

    75. //创建和构建程序对象
    76. bool CreateMemObjects(cl_context context, cl_mem memObjects[3],
    77.         float *a, float *b)
    78. {
    79.         memObjects[0] = clCreateBuffer(context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR,
    80.                 sizeof(float) * ARRAY_SIZE, a, NULL);
    81.         memObjects[1] = clCreateBuffer(context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR,
    82.                 sizeof(float) * ARRAY_SIZE, b, NULL);
    83.         memObjects[2] = clCreateBuffer(context, CL_MEM_READ_WRITE,
    84.                 sizeof(float) * ARRAY_SIZE, NULL, NULL);
    85.         return true;
    86. }


    87. // 释放OpenCL资源
    88. void Cleanup(cl_context context, cl_command_queue commandQueue,
    89.         cl_program program, cl_kernel kernel, cl_mem memObjects[3])
    90. {
    91.         for (int i = 0; i < 3; i++)
    92.         {
    93.                 if (memObjects[i] != 0)
    94.                         clReleaseMemObject(memObjects[i]);
    95.         }
    96.         if (commandQueue != 0)
    97.                 clReleaseCommandQueue(commandQueue);

    98.         if (kernel != 0)
    99.                 clReleaseKernel(kernel);

    100.         if (program != 0)
    101.                 clReleaseProgram(program);

    102.         if (context != 0)
    103.                 clReleaseContext(context);
    104. }

    105. int main(int argc, char** argv)
    106. {
    107.         cl_context context = 0;
    108.         cl_command_queue commandQueue = 0;
    109.         cl_program program = 0;
    110.         cl_device_id device = 0;
    111.         cl_kernel kernel = 0;
    112.         cl_mem memObjects[3] = { 0, 0, 0 };
    113.         cl_int errNum;

    114.         // 一、选择OpenCL平台并创建一个上下文
    115.         context = CreateContext();

    116.         // 二、 创建设备并创建命令队列
    117.         commandQueue = CreateCommandQueue(context, &device);

    118.         //创建和构建程序对象
    119.         program = CreateProgram(context, device, "HelloWorld.cl");

    120.         // 四、 创建OpenCL内核并分配内存空间
    121.         kernel = clCreateKernel(program, "hello_kernel", NULL);

    122.         //创建要处理的数据
    123.         float result[ARRAY_SIZE];
    124.         float a[ARRAY_SIZE];
    125.         float b[ARRAY_SIZE];
    126.         for (int i = 0; i < ARRAY_SIZE; i++)
    127.         {
    128.                 a[i] = (float)i;
    129.                 b[i] = 1.0;
    130.         }

    131.         //创建内存对象
    132.         if (!CreateMemObjects(context, memObjects, a, b))
    133.         {
    134.                 Cleanup(context, commandQueue, program, kernel, memObjects);
    135.                 return 1;
    136.         }

    137.         // 五、 设置内核数据并执行内核
    138.         errNum = clSetKernelArg(kernel, 0, sizeof(cl_mem), &memObjects[0]);
    139.         errNum |= clSetKernelArg(kernel, 1, sizeof(cl_mem), &memObjects[1]);
    140.         errNum |= clSetKernelArg(kernel, 2, sizeof(cl_mem), &memObjects[2]);

    141.         size_t globalWorkSize[1] = { ARRAY_SIZE };
    142.         size_t localWorkSize[1] = { 1 };

    143.         errNum = clEnqueueNDRangeKernel(commandQueue, kernel, 1, NULL,
    144.                 globalWorkSize, localWorkSize,
    145.                 0, NULL, NULL);

    146.         // 六、 读取执行结果并释放OpenCL资源
    147.         errNum = clEnqueueReadBuffer(commandQueue, memObjects[2], CL_TRUE,
    148.                 0, ARRAY_SIZE * sizeof(float), result,
    149.                 0, NULL, NULL);

    150.         for (int i = 0; i < ARRAY_SIZE; i++)
    151.         {
    152.                 std::cout << result[i] << " ";
    153.         }
    154.         std::cout << std::endl;
    155.         std::cout << "Executed program succesfully." << std::endl;
    156.         getchar();
    157.         Cleanup(context, commandQueue, program, kernel, memObjects);

    158.         return 0;
    159. }
    160. </font>
    复制代码
    (2)核函数HelloWorld.cl
    1. <font size="3" face="微软雅黑">__kernel void hello_kernel(__global const float *a,

    2.     __global const float *b,

    3.     __global float *result)

    4. {

    5.     int gid = get_global_id(0);</font>
    复制代码



    文章出处:CSDN



    签到签到
    回复

    使用道具 举报

    您需要登录后才可以回帖 注册/登录

    本版积分规则

    关闭

    站长推荐上一条 /4 下一条

    Archiver|手机版|小黑屋|恩智浦技术社区

    GMT+8, 2024-4-26 00:46 , Processed in 0.103261 second(s), 18 queries , MemCache On.

    Powered by Discuz! X3.4

    Copyright © 2001-2024, Tencent Cloud.

    快速回复 返回顶部 返回列表