首页 > 其他分享 >OpenCL中的子缓冲区例子

OpenCL中的子缓冲区例子

时间:2024-06-24 08:59:19浏览次数:28  
标签:CL cl int region OpenCL 例子 64 缓冲区

子缓冲区可以把一组数据拆分成多个部分,然后每个部分送到不同的设备上运行。这里将给出一个例子,代码的运行环境是VS2015、OpenCL3,显卡是AMD A4处理器的核芯显卡和另一个AMD的入门级独立显卡。CPP文件如下:

string kernelStr = u8R"(
    kernel void add(global const int* input, global int* output, int type)
    {
        int id = get_global_id(0);
        if (type == 0)
            output[id] = input[id] + 12;
        else
            output[id] = input[id] + 2;
    })";

int main()
{
    cl::Platform platform = cl::Platform::getDefault();
    vector<cl::Device> devices;
    platform.getDevices(CL_DEVICE_TYPE_ALL, &devices);

    for (auto& item : devices)
    {
        string name;
        item.getInfo(CL_DEVICE_NAME, &name);
        cout << name << endl;
    }

    cl::Context context(devices);
    cl::CommandQueue cmdQueueCpu(context, devices[0]);
    cl::CommandQueue cmdQueueGpu(context, devices[1]);

    cl::Program program(context, kernelStr);
    try
    {
        program.build("-cl-std=CL2.0");
    }
    catch (...)
    {
        cl_int buildErr = CL_SUCCESS;
        auto buildInfo = program.getBuildInfo<CL_PROGRAM_BUILD_LOG>(&buildErr);
        for (auto &pair : buildInfo) 
        {
            std::cerr << pair.second << std::endl << std::endl;
        }
        return -1;
    }

    vector<int> a(128, 10);
    cl::Buffer inputa(context, a.begin(), a.end(), true, true); /* 注释1 */
    cl::Buffer output1(context, CL_MEM_READ_WRITE, 64 * sizeof(int));
    cl::Buffer output2(context, CL_MEM_READ_WRITE, 64 * sizeof(int));

    cl_buffer_region region;
    region.origin = 0;
    region.size = 64 * sizeof(int); /* 字节为单位 */
    cl::Buffer mycpu = inputa.createSubBuffer(CL_MEM_READ_ONLY, CL_BUFFER_CREATE_TYPE_REGION, &region);
    region.origin = 64 * sizeof(int);
    region.size = 64 * sizeof(int);
    cl::Buffer mygpu = inputa.createSubBuffer(CL_MEM_READ_ONLY, CL_BUFFER_CREATE_TYPE_REGION, &region);

    auto kernel = cl::KernelFunctor<cl::Buffer&, cl::Buffer&, int>(program, "add");

    cl_int error = 0;
    cl::Event e1 = kernel(cl::EnqueueArgs(cmdQueueCpu, cl::NDRange(64)), mycpu, output1, 1, error);
    cl::Event e2 = kernel(cl::EnqueueArgs(cmdQueueGpu, cl::NDRange(64)), mygpu, output2, 0, error);
    vector<int> out1(64, -1), out2(64, -1);
    cl::copy(cmdQueueCpu, output1, out1.begin(), out1.end());
    cl::copy(cmdQueueGpu, output2, out2.begin(), out2.end());

    return 0;
}

上述代码就是把变量a拆分成两个64个数字的子缓冲区,然后在两个设备上计算。输出的结果如下截图,可以看出out1全是12,out2全是22,结果正确。在编程的时候需要注意cl_buffer_region的成员origin不是任意值都行,它是有对齐限制的。比如,某些显卡要求子缓冲区必须128字节对齐,那么这个值就一定要是128的整数倍,可以是0,128,256……其它值会导致createSubBuffer(...)报错。

另外上述代码中的注释1处,最后一个参数useHostPtr必须用true,否则容易运行出错或内核执行错误。原因大概是(我的猜测)在创建子缓冲区时必须用数据初始化缓冲区,而不能使用cl::copy(...)复制数据。在最后一个参数为false时,会导致创建缓冲区内部调用cl::copy(...)函数使用一个默认命令队列复制数据(见下图第二个红箭头)。源代码截图如下:

 

标签:CL,cl,int,region,OpenCL,例子,64,缓冲区
From: https://www.cnblogs.com/mengxiangdu/p/18263384

相关文章

  • OpenCL中的SVM使用案例
    SVM(共享虚拟内存)是为了解决向显卡传输数据中包含指针的问题。此时仅用cl::Buffer拷贝数据是不够的,因为数据中的指针会因为拷贝变成野指针。这就需要SVM的帮助,它可以保证数据中的指针到达GPU后仍然可以使用。这里给出一个计算单向链表中数字的和的例子。代码运行环境是VS2017,OpenCL......
  • C/C++ 缓冲区溢出问题总结
    缓冲区溢出(BufferOverflow)是一种常见的安全漏洞,它发生在当程序试图将更多的数据放入一个固定大小的内存区域(即缓冲区)时,超过了该区域所能容纳的数据量。这可能导致未定义的行为,包括数据损坏、程序崩溃,甚至更糟糕的是,攻击者可以利用这种漏洞执行恶意代码。一、缓冲区溢出概述缓冲......
  • Python学习之爬虫简单例子
    importBeautifulSoupimportpandasaspdimporturllib.request,urllib.errordefrequestUrl(url):  headers={    'User-Agent':"Mozilla/5.0(Macintosh;IntelMacOSX10_14_6)AppleWebKit/537.36(KHTML,likeGecko)Chrome/81.0.404......
  • Visual Studio + Qt项目 数组超界不会报错。 堆栈 Cookie 检测代码检测到基于堆栈
    使用vs+Qt项目时,数组超界不会崩溃和报错的问题。 开启以下2个即可。  注意:1.启用了地址擦除系统会造成QT的异常崩溃,原因未知。2.有时会报cookie的错误,数组超界了,在退出函数时才会报错。   ......
  • OpenCL中局部变量和全局变量间的异步复制内存
    本文主要是async_work_group_copy(...)和wait_group_events(...)的使用范例。展示了从全局内存到局部内存加载数据和从局部内存到全局内存写入数据。这系列内置函数可以用来取代直接赋值式的代码。不过我没有仔细对比过使用异步复制和直接赋值那个效率更高。本系列函数中还有定步......
  • mysql中先进先出的例子
    在MySQL中,实现"先进先出"(FIFO,FirstInFirstOut)的数据结构通常不直接通过数据库的表结构来完成,因为数据库表本身并不保持元素的插入顺序。然而,你可以通过几种方法来模拟FIFO的行为。以下是一个简单的例子,说明如何在MySQL中模拟FIFO队列:使用带有时间戳的表你可以创建一个......
  • Java调用mysql后台函数的例子
    在Java中调用MySQL后台的存储函数(注意,这里我们区分存储过程和存储函数:存储过程没有返回值,但可以通过输出参数返回数据;而存储函数有一个返回值)时,你需要使用CallableStatement来执行这个函数并获取返回值。以下是一个简单的例子,说明如何在Java中调用MySQL的存储函数:MySQL存储函......
  • vue通讯中provide / inject适⽤于隔代组件通信原理和例子
    在Vue中,provide和inject是用于实现跨层级组件通信的API,特别适用于隔代组件通信的场景。下面我将详细解释其原理和提供一个具体的例子。原理定义:provide:允许一个祖先组件向其所有子孙后代组件提供一个依赖,不论组件层次有多深,只要在其下游,就可以通过inject来接收。injec......
  • 【笔记】指针函数中可以返回什么样的指针,从两个例子开始(上)
    关于指针函数的两个例子:第一个例子:下面这段代码是否能正确运行?#include<stdio.h>char*get_string(){char*s="hello";returns;}intmain(){char*p;p=get_string();printf("p=%s\n",p);}因为s指向的是字符串常量,被存储在静态区(......
  • OpenCloudOS 支持 Linux 原生版微信,开启生态新篇章
    如今,微信已成为办公领域、日常生活以及娱乐方面的刚性需求软件。作为一款通用开源操作系统,OpenCloudOS积极地与微信展开Linux平台的适配工作,全方位地满足广大用户的需求。近期,经过数月的开发与测试,OpenCloudOS社区与微信团队实现了OpenCloudOS与Linux原生版微信的适配支......