AMD显卡ubuntu系统OpenCL环境搭建
1,安装显卡驱动
1)在http://support.amd.com/zh-cn/download/linux下载驱动程序,一定要注意版本
2)首先安装fglrx-core_15.302-0ubuntu1_amd64_ub_14.01.deb,可能会遇到缺少libc6-i385 lib32gcc1 dkms,执行
Sudo apt-get autoremove && sudo apt-get autoclean
Sudo apt-get -f update
Sudo apt-get -f install ibc6-i385 lib32gcc1
Sudo dpkg -i fglrx-core_15.302-0ubuntu1_amd64_ub_14.01.deb
Sudo dpkg -i fglrx_15.302-0ubuntu1_amd64_ub_14.01.deb
Sudo dpkg -i fglrx-amdcccle_15.302-0ubuntu1_amd64_ub_14.01.deb
Sudo dpkg -i fglrx-dev_15.302-0ubuntu1_amd64_ub_14.01.deb
2,安装opencl环境
1)下载SDK
http://developer.amd.com/tools-and-sdks/opencl-zone/amd-accelerated-parallel-processing-app-sdk/
2)解压 AMD-APP-SDKInstaller-v3.0.130.136-GA-linux64.tar.bz2
Sh AMD-APP-SDKInstaller-v3.0.130.136-GA-linux64.sh
3)安装好Opencl了,下面开始测试一个damo
hello_world.cpp
#include "stdafx.h"
#include <iostream>
#include <fstream>
#include "string.h"
//#include <Windows.h>
#include "CL\cl.h"
using namespace std;
#define num 16
//定义内核函数
#define KERNEL(...)#__VA_ARGS__ //宏定义:主要使得内核函数看起来更舒服。不用这个宏定义的话要么使用核函数.cl文件,要么用下面的那种方法
const char *
kernelSourceCode=KERNEL(
__kernel void hello_world(__global uint *buffer)
{
size_t gidx=get_global_id(0);
size_t gidy=get_global_id(1);
// size_t lidx=get_global_id(0);
buffer[gidx+16*gidy]=gidx+16*gidy;
});
//定义内核函数的第二种方法
//const char * kernelSourceCode="__kernel void hello_world(__global uint *buffer){size_t gidx=get_global_id(0);\nsize_t gidy=get_global_id(1);\nsize_t lidx=get_global_id(0);\nbuffer[gidx+4*gidy]=(1<<gidx)|(0x10<<gidy);\n}";
int _tmain(int argc, _TCHAR* argv[])
{
cl_int status=0;
size_t deviceListSize;
cl_uint numPlatforms;
cl_platform_id platform=NULL;
//获得平台数目,第一个参数为可加入平台列表的数目,第二个参数为平台列表,第三个参数为平台数目
//第一个参数为0的话,第二个参数一般为NULL
status= clGetPlatformIDs(0,NULL,&numPlatforms);
if(status!=CL_SUCCESS)//若返回不成功则
{
printf("Error: Getting Platforms.\n");
system("pause");
return EXIT_FAILURE;
}
if(numPlatforms>0)//若有平台的话
{
//为平台分派numPlatforms个sizeof(cl_platform_id)的内存。
cl_platform_id* platforms=(cl_platform_id*)malloc(numPlatforms*sizeof(cl_platform_id));
status = clGetPlatformIDs(numPlatforms,platforms,NULL);//获得平台列表存放在platforms,共有numPlatforms个平台。
if(status!=CL_SUCCESS)//若获得不成功的话
{
printf("Error: Getting Platform Ids.\n");
system("pause");
return -1;
}
for(unsigned int i=0;i<numPlatforms;++i)//遍历每一个平台
{
char pbuff[100];
//获取平台信息,第一个参数是平台ID,第二个参数是要查询的平台信息,第三个参数是第四个参数所指内存块的字节数,
//第四个参数与第一个参数所对应的值
status=clGetPlatformInfo(platforms[i],CL_PLATFORM_VENDOR,sizeof(pbuff),pbuff,NULL);
platform=platforms[i];
// if(!strcmp(pbuff,"Advanced Micro Devices, Inc."))//若找到平台则跳出
// printf("%s\n", pbuff);
if (!strcmp(pbuff, "NVIDIA Corporation"))
// if(!strcmp(pbuff,"Inter<R> Corporation"))
{
break;
}
}
delete platforms;
}
cl_context_properties cps[3]={CL_CONTEXT_PLATFORM,(cl_context_properties)platform,0};//指定要使用的平台
cl_context_properties* cprops=(NULL==platform)?NULL:cps;
//根据设备类型创建OPENCL上下文,第一个参数列出了上下文属性名称及其对应的值,每个属性的名称后面紧跟其对应的值,此列表以0结尾。
//第二个参数用来标识设备类型,第三个参数是应用所注册的一个回调毁掉函数,报告此上下文中所发生的错误。第四个参数是只想用户所提供的数据。
//第五个参数是用来返回错误代码的。
cl_context context = clCreateContextFromType(cprops, CL_DEVICE_TYPE_GPU, NULL, NULL, &status);
// cl_context context = clCreateContextFromType(cprops,CL_DEVICE_TYPE_CPU,NULL,NULL,&status);
if(status!=CL_SUCCESS)
{
printf("Error: creating context.\n");
system("pause");
return EXIT_FAILURE;
}
status=clGetContextInfo(context,CL_CONTEXT_DEVICES,0,NULL,&deviceListSize);//得到要为deviceid分派内存的大小。
if(status!=CL_SUCCESS)
{
printf("Error: getting context info.\n");
return EXIT_FAILURE;
}
cl_device_id *devices=(cl_device_id *)malloc(deviceListSize);//为deviceid分派内存
if(devices==0)
{
printf("Error: No device found!");
return EXIT_FAILURE;
}
//获得设备列表
//第一个参数是要查询的上下文,第二个参数是要查询的信息,第三个参数是第四个参数所指内存的字节数
//第四个参数是返回查询结果,第五个是实际返回的字节数
status = clGetContextInfo(context,CL_CONTEXT_DEVICES,deviceListSize,devices,NULL);
if(status!=CL_SUCCESS)
{
printf("Error: getting context info.\n");
return EXIT_FAILURE;
}
FILE *fp;
char *Source=NULL;
size_t SourceLength=0;
if((fopen_s(&fp,"hello_world.cl","rb"))!=0)//打开文件
{
printf("Unable to load source\n");
}
fseek(fp,0,2);//定位在文件流的尾部。
SourceLength=ftell(fp);//函数 ftell 用于得到文件位置指针当前位置相对于文件首的偏移字节数。
fseek(fp,0,0);//定位在文件流的首部。
Source=(char*)malloc((SourceLength+1)*sizeof(char));//分派内存
memset(Source,0,(SourceLength+1)*sizeof(char));//void *memset(void *s, int ch, size_t n);函数解释:将s中前n