【VS2013】OpenCl环境搭建&helloworld

来源:互联网 发布:杉帝网络 编辑:程序博客网 时间:2024/05/01 22:18

参考资料:

OpenCL编程的开发环境与API(视频)

OpenCL例程1-HelloWorld(博客)(源代码,部分修改)

OpenCL “速成”冲刺【第一天】(博客)

前面几步都比较简单,最后一步需要如下3小步:

1.项目属性->VC++目录->包含目录(include),C:\Program Files (x86)\AMD APP SDK\2.9\include。

2.项目属性->链接器->常规->附加库目录,C:\Program Files (x86)\AMD APP SDK\2.9\lib\x86。

3.项目属性->链接器->输入->附加依赖项,opencl.lib

(1设置include,错误则编译错;2、3设置lib,错误则调试运行报错:1error LNK2019: 无法解析的外部符号 _clGetPlatformIDs@12,SDK,lib目录下有32bit和64bit,选择不对也会报错


修改:

1."stdafx.h"无法包含

2._TCHAR找不到,#include <tchar.h>

3._tmain的return前加system("pause");//避免执行窗口完闪退

// OpenCl-1.cpp : Defines the entry point for the console application.////#include "stdafx.h" 项目属性c/c++预编译头里本来就有#include <tchar.h>#include <CL/cl.h>#include <iostream>#include <fstream>#include <stdio.h>#include <stdlib.h>#include <string>using namespace std;cl_int ConvertToString(const char *pFileName, std::string &str);int _tmain(int argc, _TCHAR* argv[]){cl_intiStatus = 0;// 函数返回状态cl_uintuiNumPlatforms = 0;// 平台个数cl_platform_idPlatform = NULL;// 选择的平台size_tuiSize = 0;// 平台版本名字字节数cl_intiErr = 0;// 返回参数char*pName = NULL;// 平台版本名cl_uintuiNumDevices = 0;// 设备数量cl_device_id*pDevices = NULL;// 设备cl_contextContext = NULL;// 设备环境cl_command_queueCommandQueue = NULL;// 命令队列const char*pFileName = "HelloWorld_Kernel.cl";// cl文件名stringstrSource = "";// 用于存储cl文件中的代码const char*pSource;// 代码字符串指针size_tuiArrSourceSize[] = { 0 };// 代码字符串长度cl_programProgram = NULL;// 程序对象const char*pInput = "gdkknvnqkc";// 输入字符串size_tuiStrlength = strlen(pInput);// 输入字符串长度char*pOutput = NULL;// 输出字符串cl_memmemInutBuffer = NULL;// 输入内存对象cl_memmemOutputBuffer = NULL;// 输出内存对象cl_kernelKernel = NULL;// 内核对象size_tuiGlobal_Work_Size[1] = { 0 };// 用于设定内核分布//-------------------1. 获得并选择可用平台-----------------------------// 查询可用的平台个数,并返回状态iStatus = clGetPlatformIDs(0, NULL, &uiNumPlatforms);if (CL_SUCCESS != iStatus){cout << "Error: Getting platforms error" << endl;return 0;}// 获得平台地址if (uiNumPlatforms > 0)  // 如果有可用平台{// 根据平台数为平台分配内存空间cl_platform_id *pPlatforms = (cl_platform_id *)malloc(uiNumPlatforms * sizeof(cl_platform_id));// 获得可用的平台iStatus = clGetPlatformIDs(uiNumPlatforms, pPlatforms, NULL);Platform = pPlatforms[0];// 获得第一个平台的地址free(pPlatforms);// 释放平台占用的内存空间}// 获得平台版本名// 获得平台版本名的字节数iErr = clGetPlatformInfo(Platform, CL_PLATFORM_VERSION, 0, NULL, &uiSize);// 根据字节数为平台版本名分配内存空间pName = (char *)alloca(uiSize * sizeof(char));// 获得平台版本名字iErr = clGetPlatformInfo(Platform, CL_PLATFORM_VERSION, uiSize, pName, NULL);cout << pName << endl;//--------------2. 查询GPU设备,并选择可用设备------------------------// 获得GPU设备数量iStatus = clGetDeviceIDs(Platform, CL_DEVICE_TYPE_GPU, 0, NULL, &uiNumDevices);if (0 == uiNumDevices)// 如果没有GPU设备{cout << "No GPU device available." << endl;cout << "Choose CPU as default device." << endl;// 选择CPU作为设备,获得设备数iStatus = clGetDeviceIDs(Platform, CL_DEVICE_TYPE_CPU, 0, NULL, &uiNumDevices);// 为设备分配空间pDevices = (cl_device_id *)malloc(uiNumDevices * sizeof(cl_device_id));// 获得平台iStatus = clGetDeviceIDs(Platform, CL_DEVICE_TYPE_CPU, uiNumDevices, pDevices, NULL);}else{pDevices = (cl_device_id *)malloc(uiNumDevices * sizeof(cl_device_id));iStatus = clGetDeviceIDs(Platform, CL_DEVICE_TYPE_GPU, uiNumDevices, pDevices, NULL);}// -------------------3.创建设备环境---------------------------------// 创建设备环境Context = clCreateContext(NULL, 1, pDevices, NULL, NULL, NULL);if (NULL == Context){cout << "Error: Can not create context" << endl;return 0;}// -------------------4.创建命令队列--------------------------------------// 创建第1个设备的命令队列CommandQueue = clCreateCommandQueue(Context, pDevices[0], 0, NULL);if (NULL == CommandQueue){cout << "Error: Can not create CommandQueue" << endl;return 0;}// ----------------------5. 创建程序对象------------------------------// 将cl文件中的代码转为字符串iStatus = ConvertToString(pFileName, strSource);pSource = strSource.c_str();// 获得strSource指针uiArrSourceSize[0] = strlen(pSource);// 字符串大小// 创建程序对象Program = clCreateProgramWithSource(Context, 1, &pSource, uiArrSourceSize, NULL);if (NULL == Program){cout << "Error: Can not create program" << endl;return 0;}// -----------------------------6. 编译程序--------------------------------// 编译程序iStatus = clBuildProgram(Program, 1, pDevices, NULL, NULL, NULL);if (CL_SUCCESS != iStatus)// 编译错误{cout << "Error: Can not build program" << endl;char szBuildLog[16384];clGetProgramBuildInfo(Program, *pDevices, CL_PROGRAM_BUILD_LOG, sizeof(szBuildLog), szBuildLog, NULL);cout << "Error in Kernel: " << endl << szBuildLog;clReleaseProgram(Program);return 0;}//-------------------------7. 并创建输入输出内核内存对象--------------------------------// 创建输入内存对象memInutBuffer = clCreateBuffer(Context,CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR,  // 输入内存为只读,并可以从宿主机内存复制到设备内存(uiStrlength + 1) * sizeof(char),  // 输入内存空间大小(void *)pInput,NULL);// 创建输出内存对象memOutputBuffer = clCreateBuffer(Context,CL_MEM_WRITE_ONLY,// 输出内存只能写(uiStrlength + 1) * sizeof(char),// 输出内存空间大小NULL,NULL);if ((NULL == memInutBuffer) || (NULL == memOutputBuffer)){cout << "Error creating memory objects" << endl;return 0;}//--------------------------8. 创建内核对象-------------------------------------Kernel = clCreateKernel(Program,"helloworld",  // cl文件中的入口函数NULL);if (NULL == Kernel){cout << "Error: Can not create kernel" << endl;return 0;}//----------------------------9. 设置内核参数----------------------------------iStatus = clSetKernelArg(Kernel,0,// 参数索引sizeof(cl_mem),(void *)&memInutBuffer);iStatus |= clSetKernelArg(Kernel, 1, sizeof(cl_mem), (void *)&memOutputBuffer);if (CL_SUCCESS != iStatus){cout << "Error setting kernel arguments" << endl;}// --------------------------10.运行内核---------------------------------uiGlobal_Work_Size[0] = uiStrlength;  // 输入字符串大小// 利用命令队列使将再设备上执行的内核排队iStatus = clEnqueueNDRangeKernel(CommandQueue,Kernel,1,NULL,uiGlobal_Work_Size,  // 确定内核在设备上的多个处理单元间的分布NULL, // 确定内核在设备上的多个处理单元间的分布0,NULL,NULL);if (CL_SUCCESS != iStatus){cout << "Error: Can not run kernel" << endl;return 0;}// ----------------------------11. 将输出读取到主机内存pOutput = (char *)malloc(uiStrlength + 1);  // uiStrlength 为 输入字符串长度iStatus = clEnqueueReadBuffer(CommandQueue,// 命令队列memOutputBuffer,// 输出内存对象CL_TRUE,// 内核读取结束之前该函数不会返回0,uiStrlength * sizeof(char),pOutput,0,NULL,NULL);if (CL_SUCCESS != iStatus){cout << "Error: Can not reading result buffer" << endl;return 0;}// ---------------------12--输出计算结果---------------pOutput[uiStrlength] = '\0';cout << "Input String:" << endl;cout << pInput << endl;cout << "Output String:" << endl;cout << pOutput << endl;// -------------------------------13. 释放资源--------------------------------iStatus = clReleaseKernel(Kernel);iStatus = clReleaseProgram(Program);iStatus = clReleaseMemObject(memInutBuffer);iStatus = clReleaseMemObject(memOutputBuffer);iStatus = clReleaseCommandQueue(CommandQueue);iStatus = clReleaseContext(Context);if (NULL != pOutput){free(pOutput);pOutput = NULL;}if (NULL != pDevices){free(pDevices);pDevices = NULL;}system("pause");//避免执行完闪退return 0;}// 将cl文件代码转为字符串cl_int ConvertToString(const char *pFileName, std::string &Str){size_tuiSize = 0;size_tuiFileSize = 0;char*pStr = NULL;std::fstream fFile(pFileName, (std::fstream::in | std::fstream::binary));if (fFile.is_open()){fFile.seekg(0, std::fstream::end);uiSize = uiFileSize = (size_t)fFile.tellg();  // 获得文件大小fFile.seekg(0, std::fstream::beg);pStr = new char[uiSize + 1];if (NULL == pStr){fFile.close();return 0;}fFile.read(pStr, uiFileSize);// 读取uiFileSize字节fFile.close();pStr[uiSize] = '\0';Str = pStr;delete[] pStr;return 0;}cout << "Error: Failed to open cl file\n:" << pFileName << endl;return -1;}


HelloWorld_Kernel.cl文件,在上面的源文件开头变量声明里有(28)const char*pFileName = "HelloWorld_Kernel.cl";// cl文件名

__kernel void helloworld(__global char *pIn, __global char *pOut){int iNum = get_global_id(0);pOut[iNum] = pIn[iNum] + 1;}

运行结果:



0 0
原创粉丝点击