对opencl helloworld代码的修正

2023-10-29

由于代码比较乱,数组也容易越界,故重新加了个类,用了stl::vector,代码如下

test.cl

__kernel void hello_kernel(    __global const float * a,
                            __global const float * b,
                            __global float* result )
{
    int gid = get_global_id(0);
    result[gid] = a[gid] + b[gid];                            

}


头文件

#pragma once
#include <iostream>
#include <fstream>
#include <sstream>
#include <time.h>
#include <vector>


#ifdef __APPLE__
#include <opencl/cl.h>
#else
#include <CL/cl.h>
#endif

//读写内存
enum readWrite
{
    readOnly = 0,  //只读
    rw = 1            //读写
};

class myOpenCL
{
public:
    myOpenCL(std::string strOpenCLFileName,
        std::string strOpenCLKernalEntry,
        int objectSize,
        int numberOfEachObject,
        int sizeOfEachUnit,
        std::vector<std::vector<float>> inputVec2);
    ~myOpenCL();

public:
    //处理全过程
    void process();
    //返回结果
    std::vector<float> getResult();
    //为cpu平台创建上下文
    cl_context createContext();
    //选择第一个可用设备,并创建一个命令队列
    cl_command_queue createCommandQueue(cl_context context, cl_device_id & device);
    //从磁盘加载内核源文件创建和构建一个程序对象
    cl_program createProgram( const char* fileName);
    //建立内核参数
    cl_int setKernelParameter(int id, cl_mem theData);
    //使用命令队列使将在设备上执行的内核排队
    cl_int setKernalQueue(size_t* globalWorkSize, size_t* localWorkSize);
    //从内核读回结果
    cl_int readResult(cl_mem memObject, float * result);

public:
    //返回设备上下文
    cl_context getContext();
private:
    std::string _strOpenCLFileName; //opencl处理的文件名称
    std::string _strOpenCLKernalEntry;//opencl入口名称
    cl_context _theContext;        //设备上下文
    cl_command_queue _commandQueue;//命令队列
    cl_device_id  _device;    //设备ID
    cl_program _theProgram; //程序对象
    cl_kernel _theKernel;//创建opencl内核    
    int _objectSize;        //物体的数目
    int _numberOfEachObject;    //每个物体含多少值
    int _sizeOfEachUnit;    //每个值的大小
    std::vector<std::vector<float>> _inputVec2;//输入的vector
    
};


实现文件

#include "myOpenCL.h"
myOpenCL::myOpenCL(std::string strOpenCLFileName,
    std::string strOpenCLKernalEntry,
    int objectSize,
    int numberOfEachObject,
    int sizeOfEachUnit,
    std::vector<std::vector<float>> inputVec2)
{
    _strOpenCLFileName = strOpenCLFileName;
    _strOpenCLKernalEntry = strOpenCLKernalEntry;
    _objectSize = objectSize;
    _numberOfEachObject = numberOfEachObject;
    _sizeOfEachUnit = sizeOfEachUnit;
    _inputVec2 = inputVec2;
    _theContext = NULL;
    _commandQueue = NULL;
    _theProgram = NULL;
    _theKernel = NULL;

}

myOpenCL::~myOpenCL()
{
    _inputVec2.clear();
    if (_commandQueue != 0)
    {
        clReleaseCommandQueue(_commandQueue);
    }

    if (_theKernel != 0)
    {
        clReleaseKernel(_theKernel);
    }
    if (_theProgram != 0)
    {
        clReleaseProgram(_theProgram);
    }
    if (_theContext != 0)
    {
        clReleaseContext(_theContext);
    }
}

//为cpu平台创建上下文
cl_context myOpenCL::createContext()
{
    cl_platform_id firstPlatformId = 0;
    cl_uint numPlatforms = 0;
    //这里选择第一个平台
    cl_int errNum = clGetPlatformIDs(1, &firstPlatformId, &numPlatforms);
    //创建平台的一个上下文,先试图创建一个gpu的,如果没有的话,就创建cpu的
    cl_context_properties contextProperties[] =
    {
        CL_CONTEXT_PLATFORM,
        (cl_context_properties)firstPlatformId,
        0
    };
    cl_context context = clCreateContextFromType(contextProperties, CL_DEVICE_TYPE_GPU, NULL, NULL, &errNum);
    if (errNum != CL_SUCCESS)
    {
        context = clCreateContextFromType(contextProperties, CL_DEVICE_TYPE_CPU, NULL, NULL, &errNum);
    }
    return context;
}
//选择第一个可用设备,并创建一个命令队列
cl_command_queue myOpenCL::createCommandQueue(cl_context context, cl_device_id & device)
{
    size_t deviceBufferSize = -1;
    clGetContextInfo(context, CL_CONTEXT_DEVICES, 0, NULL, &deviceBufferSize);
    //为设备缓存分配空间
    cl_device_id * devices = new cl_device_id[deviceBufferSize / sizeof(cl_device_id)];
    clGetContextInfo(context, CL_CONTEXT_DEVICES, deviceBufferSize, devices, NULL);
    //这里只选择第一个可用的设备,在该设备创建一个命令队列.这个命令队列用于将程序中要执行的内核排队,并读回结果
    cl_command_queue commandQueue = clCreateCommandQueue(context, devices[0], 0, NULL);
    
    device = devices[0];
    delete[] devices;
    return commandQueue;
}

//从磁盘加载内核源文件创建和构建一个程序对象
cl_program myOpenCL::createProgram( const char* fileName)
{
    std::ifstream kernelFile(fileName, std::ios::in);
    if (!kernelFile.is_open())
    {
        std::cerr << "不能打开文件" << fileName << std::endl;
        return NULL;
    }

    std::ostringstream oss;
    oss << kernelFile.rdbuf();
    std::string srcStdStr = oss.str();
    const char * srcStr = srcStdStr.c_str();
    //创建程序对象
    cl_program program = clCreateProgramWithSource(_theContext, 1, (const char**)&srcStr, NULL, NULL);
    //编译内核源码
    clBuildProgram(program, 0, NULL, NULL, NULL, NULL);
    return program;
}

//返回设备上下文
cl_context myOpenCL::getContext()
{
    return _theContext;
}

//建立内核参数
cl_int myOpenCL::setKernelParameter( int id, cl_mem theData)
{
    cl_int errNum = clSetKernelArg(_theKernel, id, sizeof(cl_mem), &theData);
    return errNum;
}

//使用命令队列使将在设备上执行的内核排队
cl_int myOpenCL::setKernalQueue(size_t* globalWorkSize, size_t* localWorkSize)
{
    cl_int errNum = clEnqueueNDRangeKernel(_commandQueue, _theKernel, 1, NULL, globalWorkSize, localWorkSize, 0, NULL, NULL);
    return errNum;
}
//从内核读回结果
cl_int myOpenCL::readResult(cl_mem memObject, float * result)
{
    cl_int errNum = clEnqueueReadBuffer(_commandQueue, memObject, CL_TRUE, 0, _numberOfEachObject * _sizeOfEachUnit, result, 0, NULL, NULL);
    return errNum;
}

//处理全过程
void myOpenCL::process()
{
    _theContext = this->createContext();
    _commandQueue = this->createCommandQueue(_theContext, _device);
    _theProgram = this->createProgram(_strOpenCLFileName.c_str());
    //创建opencl内核
    _theKernel = clCreateKernel(_theProgram, _strOpenCLKernalEntry.c_str(), NULL);

    //读写vector,用以在分配内存时判断只读还是读写
    //设定前几个只读,最后一个读写
    std::vector<int> readWriteVector;
    readWriteVector.clear();
    readWriteVector.resize(_objectSize);
    for (size_t i = 0; i < _objectSize - 1; i++)
    {
        readWriteVector[i] = readWrite::readOnly;
    }
    readWriteVector[_objectSize - 1] = readWrite::rw;

    std::vector<cl_mem> memObjectVector;
    memObjectVector.clear();
    memObjectVector.resize(_objectSize);
    for (size_t i = 0; i < _objectSize; i++)
    {
        memObjectVector[i] = 0;
    }

    cl_context theContext = this->getContext();
    //先读后写分配内存
    for (size_t i = 0; i < _objectSize; i++)
    {
        int readW = readWriteVector[i];
        if (readW == readWrite::readOnly)
        {
            memObjectVector[i] = clCreateBuffer(theContext, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR,
                sizeof(float) * _numberOfEachObject, &_inputVec2[i][0], NULL);
        }
        else if (readW == readWrite::rw)
        {
            memObjectVector[i] = clCreateBuffer(theContext, CL_MEM_READ_WRITE, _sizeOfEachUnit * _numberOfEachObject, NULL, NULL);
        }
    }

    //建立内核参数
    for (size_t i = 0; i < _objectSize; i++)
    {
        this->setKernelParameter(i, memObjectVector[i]);
    }
    //使用命令队列使将在设备上执行的内核排队
    size_t globalWorkSize[1] = { _numberOfEachObject };
    size_t localWorkSize[1] = { 1 };
    this->setKernalQueue(globalWorkSize, localWorkSize);
    //从内核读回结果
    this->readResult(memObjectVector[_objectSize - 1], &_inputVec2[_objectSize - 1][0]);
    memObjectVector.clear();
}

//返回结果
std::vector<float> myOpenCL::getResult()
{
    return _inputVec2[_objectSize - 1];
}

调用文件


#include "myOpenCL.h"

const int ARRAY_SIZE = 1000000;

int main(int argc, char ** argv)
{
    std::string strFileName = "test.cl";
    std::string strOpenCLKernalEntry = "hello_kernel";
    int objectSize = 3;
    int numberOfEachObject = ARRAY_SIZE;

    //设定各单元数值
    std::vector<std::vector<float>> computeVector;
    computeVector.clear();
    computeVector.resize(objectSize);
    for (size_t j = 0; j < objectSize; j++)
    {
        computeVector[j].resize(numberOfEachObject);
    }

    for (size_t i = 0; i < numberOfEachObject; i++)
    {
        computeVector[0][i] = (float)i;
        computeVector[1][i] = (float)(i * 2);
    }

    myOpenCL theOpenCL(strFileName, strOpenCLKernalEntry,objectSize,numberOfEachObject,sizeof(float),computeVector);
    theOpenCL.process();
    //输出结果
    std::vector<float> resultVec = theOpenCL.getResult();
    int sizeOfResult = resultVec.size();
    for (size_t i = 0; i < sizeOfResult; i++)
    {
        if (i % 10 == 0)
        {
            std::cout << std::endl;
        }
        float theResult = resultVec[i];
        std::cout << theResult << ",";
    }

    return 0;
}


本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

对opencl helloworld代码的修正 的相关文章

  • 确定 OpenCL 工作组大小的限制因素?

    我正在尝试在资源较少的嵌入式 GPU 上运行一些为桌面显卡编写的 OpenCL 内核 特别是 桌面版本假设始终支持至少 256 个工作组大小 但基于 Mali T628 ARM 的 GPU 仅保证 64 工作组大小 事实上 一些内核报告CL
  • 为什么 Cuda/OpenCL 的全局内存中不存在库冲突?

    我还没有弄清楚并且谷歌没有帮助我的一件事是 为什么有可能与共享内存发生银行冲突 但在全局内存中却没有 银行与寄存器会存在冲突吗 UPDATE哇 我真的很感谢 Tibbit 和 Grizzly 的两个回答 看来我只能给一个答案打绿色复选标记
  • 什么样的工作受益于 OpenCL

    首先 我很清楚 OpenCL 并没有神奇地让一切变得更快 我很清楚 OpenCL 有局限性 现在回答我的问题 我习惯使用编程进行不同的科学计算 我处理的一些事情在计算的复杂性和数量方面非常激烈 所以我想知道 也许我可以使用 OpenCL 来
  • PyOpenCL 中的时间测量

    我正在 FPGA 和 GPU 中使用 PyOpenCL 运行内核 为了测量执行所需的时间 我使用 t1 time event mykernel queue c width c height block size block size d c
  • 数组大小和复制性能

    我确信这个问题之前已经得到了回答 但我找不到一个好的解释 我正在编写一个图形程序 其中管道的一部分将体素数据复制到 OpenCL 页面锁定 固定 内存 我发现这个复制过程是一个瓶颈 并对一个简单的性能进行了一些测量std copy 数据是浮
  • OpenCL 动态并行/GPU 生成的线程?

    CUDA 5 刚刚被释放 http nvidianews nvidia com Releases NVIDIA Releases CUDA 5 Making Programming With World s Most Pervasive P
  • 工作组之间的 OpenCL 同步

    是否可以同步 OpenCL 工作组 例如 我有 100 个工作组 每个工作组只有一个项目 不要问我为什么 这是一个例子 我需要对每个工作项设置障碍 以确保所有工作组都会在这 100 个工作组中的每个工作项达到此障碍点后继续 不 你不能 您可
  • 如何在 OpenCL 中验证波前/扭曲大小?

    我使用的是 AMD Radeon HD 7700 GPU 我想使用以下内核来验证波前尺寸是否为 64 kernel void kernel test warpsize global T dataSet uint size size t id
  • OpenCL - 将树复制到设备内存

    我用 C 代码实现了二叉搜索树 我的每个树节点如下所示 typedef struct treeNode int key struct treeNode right struct treeNode left treeNode t 宿主建造的树
  • GPU 显存带宽理论与实际

    作为在 GPU 上运行的算法分析的一部分 我觉得我正在达到内存带宽的要求 我有几个复杂的内核执行一些复杂的操作 稀疏矩阵乘法 归约等 和一些非常简单的操作 当我计算每个内核读取 写入的总数据时 似乎所有 重要的 都达到了约 79GB s 的
  • 为什么 AMD GCN 使用非零 NULL?

    这次提交 https reviews llvm org rL289252 says In amdgcn https en wikipedia org wiki Graphics Core Next目标 全局 常量和通用地址空间中的空指针取值
  • 有多少线程(或工作项)可以同时运行?

    我是 GPGPU 编程新手 正在研究 OpenCL 的 NVIDIA 实现 我的问题是如何计算 GPU 设备的限制 线程数 据我了解 有许多工作组 相当于 CUDA 中的块 其中包含许多工作项 cuda 线程 如何获取我的卡上存在的工作组数
  • PyOpenCL 矩阵乘法

    我有使用 pyopenCL 进行矩阵乘法的代码 我的问题是某些矩阵的结果是错误的 我不明白为什么 经过一番研究后 我认为它与类似的全球规模有关 但我不明白如何设置该值 例如 使用 numpy dtype float32 的矩阵 矩阵1 0
  • CUDA PTX 代码 %envreg<32> 特殊寄存器

    我尝试使用 CUDA 驱动程序 API 运行由 cl 内核生成的 PTX 汇编代码 我采取的步骤是这些 标准 opencl 程序 1 加载 cl内核 2 JIT编译 3 获取编译好的ptx代码并保存 到目前为止 一切都很好 我注意到 ptx
  • boost::计算流压缩

    如何使用 boost compute 进行流压缩 例如 如果您只想对数组中的某些元素执行繁重的操作 首先 生成掩码数组 其中包含与要执行操作的元素相对应的元素 mask 0 0 0 1 1 0 1 0 1 然后对掩码数组进行排它扫描 前缀和
  • 官方 OpenCL 2.2 标准是否支持 WaveFront?

    众所周知 AMD OpenCL 支持 WaveFront 2015 年 8 月 http amd dev wpengine netdna cdn com wordpress media 2013 12 AMD OpenCL Programm
  • 使用 OpenCL 支持构建 OpenCV

    在 CMake 中 我使用 OpenCL Enable ON 构建了 OpenCV 它自动检测到OPENCL INCLUDE DIR路径但是OPENCL LIBRARY即使单击配置后也是空的 为了OPENCL LIBRARY我也没有看到浏览
  • 如何在 Emgu CV 项目中利用 OpenCL

    我是使用 Emgu CV 的新手 并开始创建小型示例项目 例如面部检测 眼睛检测等 如果我可以利用 OpenCL 来加速使用 GPU 的过程 那就太好了 否则 当我降低scaleFactor时 它会导致大量的CPU利用率 我怎样才能做到这一
  • 用 OpenCL C 编写快速线性系统求解器

    我正在编写一个 OpenCL 内核 它将涉及求解线性系统 目前我的内核太慢了 提高线性系统部分的性能似乎是一个不错的起点 我还应该注意 我并没有尝试使我的线性求解器并行 我正在研究的问题在宏观层面上已经是令人尴尬的并行 以下是我编写的 C
  • 用于计算邻居列表的最佳 GPU 算法

    给定 3D 中数千个点的集合 我需要获取落在某个截止值 以欧几里得距离而言 内的每个粒子的邻居列表 并且如果可能的话 从最近到最远排序 在 CUDA 或 OpenCL 语言中 哪种 GPU 算法最快 我所知道的最快的 GPU MD 代码之一

随机推荐

  • Linux下如何配置环境变量

    基础知识 首先 我们来了解一下什么是 环境变量 环境变量 通俗讲是操作系统或程序执行时候默认设定的参数 比如 PATH 路径变量 当要执行某个命令或程序的时候默认寻找的路径 然后 我们再来了解一下环境变量都有哪些类型 环境变量的分类 根据变
  • C++的类型

    C 的类型 按照标准 C 只有两种类型 基本类型和复合类型 但是里面细节多导致彻底理解它们有难度 所以这里只是简单总结一下 基本类型 基本类型分成算术类型和两种特殊的类型 算术类型 算术类型分成整数类型和浮点数类型两种 整数类型 以下都是整
  • 在springboot中使用Sse(Server-sent Events)Web实时通信技术-服务器发送事件SseEmitter

    最近在练习项目时需要用到消息实时推送技术 了解到有两种实时通信技术供我选择 SSE和WebSocket 详细了解后得知SSE是基于http协议 无需导入其他依赖 特点是服务端主动给客户端推送消息 单向 适合浏览器端只做数据接收 而webso
  • 华为OD机试真题-路灯照明问题-2023年OD统一考试(B卷)

    题目描述 在一条笔直的公路上安装了N个路灯 从位置0开始安装 路灯之间间距固定为100米 每个路灯都有自己的照明半径 请计算第一个路灯和最后一个路灯之间 无法照明的区间的长度和 输入描述 第一行为一个数N 表示路灯个数 1 lt N lt
  • Pysot训练自己的数据集

    数据集预处理操作 Pysot训练自己数据集前的预处理 Vesper0412的博客 CSDN博客 Pysot源码地址 https github com STVIR pysot 1 linux系统激活环境 conda activate pyto
  • 机器学习课程学习阶段总结

    机器学习课程学习阶段总结 线性回归 逻辑回归 逻辑回归 是一种分类算法 和之前的线性回归不是同一类问题 但是对于处理问题上有相同的思想 对于线性回归问题 有较容易理解的思路 首先指定一个形式确定的 h x Tx h theta x thet
  • 笔记本连接RK61键机械键盘非损坏的win和alt对调,数字键失灵以及特殊字母键失灵恢复

    1 问题描述 在打游戏或者码字的时候 无意中按下了键盘模式切换按键 导致了键盘的假性失灵状态 具体表现为 1 win和alt键功能对调 win按键无反应 alt键出现windows窗口 虽然不影响使用 但是很别扭 2 数字键失灵 键盘打不出
  • 网络安全有哪些经典笑话

    今天程序员同事发了一个链接给我 点开是一个调侃程序员有哪些经典笑话的帖子 给我看乐了 诸如 老婆给当程序员的老公打电话 下班顺路买一斤包子带回来 如果看到卖西瓜的 就买一个 当晚 程序员老公手捧一个包子进了家门 老婆怒道 你怎么就买了一个包
  • Android BLE 快速开发示例

    目录 概述 1 FastBle的使用 2 BLE开发实践方面的理解 3 FastBle源码解析 概述 思来想去 还是写这篇博文 记录一下 当时学习BLE的一些心得 重捡回当前Android知识 想深入了解蓝牙通讯知识 这个案例是非常不错的选
  • 毕业设计 - 基于单片机的测谎仪

    文章目录 1 简介 2 实现原理 3 主要器件 4 实现效果 正常情况 未说谎 异常情况 说谎了 5 部分实现代码 6 最后 1 简介 Hi 大家好 学长今天向大家介绍一个有趣的单片项目 基于单片机的测谎仪 大家可用于 课程设计 或 毕业设
  • 大数据技术(林子雨版)——期末复习知识点

    gt 大数据 云计算 大数据时代的三次信息化浪潮 时间 标志 解决的问题 代表企业 1980年前后 个人计算机 信息处理 Intel IBM 1995年前后 互联网 信息传输 谷歌 腾讯 2010年前后 大数据 云计算 物联网 信息爆炸 亚
  • Windows “Win+R“命令行运行常用命令

    Windows Win R 命令行运行常用命令 Windows操作系统提供了许多方便的方式来执行各种任务 其中之一是使用 Win R 运行命令行 这个快捷键组合可以让您迅速启动各种应用程序 工具和系统实用程序 而无需通过开始菜单或桌面快捷方
  • 【仲裁器】轮询仲裁round-robin,rr

    起因 在多主单从的设计中 当多个源端同时发起传输请求时 需要仲裁器根据优先级来判断响应哪一个源端 轮询仲裁 各个源端优先级相同 当其同时发起请求时 依次进行响应 电路图 代码 module rr arb input clk input rs
  • 区块链(二)-私有链的搭建

    私有链 搭建私有链 首先需要写一个创世块文件 创世块就是我自己链上的第一个区块 config nonce 0x0000000000000042 mixhash 0x00000000000000000000000000000000000000
  • 简单介绍Hyperledger fabric是什么

    Hyperledger Fabric作为超级账本的项目之一 目前基于它开发的区块链项目非常多 Linux基金会于2015年成立超级账本 以推进跨行业的区块链技术 相对于申报一个区块链标准 它鼓励通过社区合作的方式来发展区块链技术 带着知识产
  • 论git中使用https和ssh协议的区别

    论git中使用https和ssh协议的区别 SHELDON CUI S BLOG 2017 09 08 git https ssh 心得 http好还是ssh好 git可以使用四种主要的协议来传输资料 本地协议 Local HTTP 协议
  • TightVNC H264编解码(一)

    时光流逝 时间过的真快啊 疲于工作 发现近一个多月没写文章了 此文算是对最近的工作做个总结吧 经过尽二个月的不断摸索 TightVNC终于支持H264编解码了 前期真正编写H264编解码器只花了一周左右时间 但是测试发现效果并不是太理想 帧
  • 2022年android面试题,Android资深架构师分享学习经验及总结

    前言 最近有些朋友提问 Android QQ空间 换肤实现原理是什么 于是 我决定在这里做一下回答 对这个方面感兴趣的朋友也可以来看下 手q的换肤机制主要是通过拦截系统resource中的sPreloadedDrawables静态缓存变量
  • 为什么说“低估值买入,买到即赚到”?

    投资究竟能不能挣到钱 到底是由哪个环节决定的 买入还是卖出 直觉上说 这个问题的答案理所当然是 卖出 就连路边卖杂货的小商贩都明白 只要卖出价高于买入价 就可以挣到钱 直到我看了 穷查理宝典 接触到价值投资的理念 想法有了根本性改变 买入的
  • 对opencl helloworld代码的修正

    由于代码比较乱 数组也容易越界 故重新加了个类 用了stl vector 代码如下 test cl kernel void hello kernel global const float a global const float b glo