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个字节 (typedef unsigned int size_t )用 ch 替换并返回 s
if(fread(Source,SourceLength,1,fp)!=1)
{
printf("Cannot read source file\n");
}
// size_t sourcesize[]={strlen(kernelSourceCode)};//获取内核代码的长度
//为上下文创建程序对象
//第一个参数必须是有效的上下文,第二个参数表示有多少个字符串指针数组组成,第三个参数是源代码码源,
//第四个参数表示源代码长度,第五个表示返回错误类型。
cl_program program=clCreateProgramWithSource(context,1,(const char **)&Source,&SourceLength,&status);
if(status!=CL_SUCCESS)
{
printf("Error:loading source into cl_program.\n");
}
//为program关联的上下文的所有设备构建程序执行体或二进制代码。
//第一个参数为程序对象,第二个参数是设备数目,第三个参数是设备列表。
//第四个参数是编译选项,第五个是回调函数,第六个是回调函数的参数。
status=clBuildProgram(program,1,devices,NULL,NULL,NULL);
if(status!=CL_SUCCESS)
{
printf("Error:building program\n");
system("pause");
}
//创建内核对象
//第一个参数是带有成功构建的执行体的程序对象,第二个程序中带有_kernel限定符的函数名字。
//第三个是返回错误类型。
cl_kernel kernel=clCreateKernel(program,"hello_world",&status);
if(status!=CL_SUCCESS)
{
printf("Error:creating kernel form program.\n");
system("pause");
return EXIT_FAILURE;
}
//在特定的设备上创建命令队列
//第一个参数是有效的上下文,第二个参数是与上下文关联的一个设备。
//第三个参数是指向命令队列的属性。第四个参数是返回错误类型
cl_command_queue commendQueue=clCreateCommandQueue(context,devices[0],0,&status);
if(status!=CL_SUCCESS)
{
printf("Error:creating commend queue.\n");
return EXIT_FAILURE;
}
unsigned int *outbuffer=new unsigned int [num*num];
memset(outbuffer,0,num*num*4);//填充OUTBUFFER为0
//创建缓存对象
//第一个参数是有效的上下文,第二个参数是用来指定分派和使用信息。,第三个参数是所分派缓存对象的字节数
//第四个参数指向有应用所分派的缓存数据,第五个是返回错误类型。
cl_mem outputbuffer=clCreateBuffer(context,CL_MEM_ALLOC_HOST_PTR,num*num*4,NULL,&status);
if(status!=CL_SUCCESS)
{
printf("Error:clCreateBuffer.\n");
return EXIT_FAILURE;
}
//用来设置内核函数参数的值
//第一个参数是一个有效的内核对象,第二个参数是参数的索引,第三个参数是参数的大小
//第四个参数是参数
int a=num;
// status=clSetKernelArg(kernel,1,sizeof(int),(void*)&a);
status=clSetKernelArg(kernel,0,sizeof(cl_mem),(void*)&outputbuffer);
if(status!=CL_SUCCESS)
{
printf("Error:setting lernel argument.\n");
return EXIT_FAILURE;
}
size_t globalThreads[]={num,num};
size_t localThreads[]={num/2,num/2};
//将一个命令入队
//第一个参数是一个有效的命令,第二个参数是一个有效的内核,第三个参数是维数,第四个参数为NULL
//第五个参数全局工作组数目,第六个是局部工作组数目,第7,8,9个是设置内核执行前的等待事件。
status=clEnqueueNDRangeKernel(commendQueue,kernel,2,NULL,globalThreads,localThreads,0,NULL,NULL);
if(status!=CL_SUCCESS)
{
printf("Error:enqueueing kernel\n");
system("pause");
return EXIT_FAILURE;
}
//会阻塞,知道之前入队的所有OPENCL命令全部提交并完成
//一个有效的命令队列
status=clFinish(commendQueue);
if(status!=CL_SUCCESS)
{
printf("Error: finish commend queue\n");
return EXIT_FAILURE;
}
//将缓存内存读入宿主机
//第一个参数容纳读写命令的命令队列,第二个是有效的缓存对象,
//第五个参数是读取的字节数,第六个参数指向宿主机内存,第7,8,9是在执行读取命令前要等待是事件设置。
status=clEnqueueReadBuffer(commendQueue,outputbuffer,CL_TRUE,0,num*num*4,outbuffer,0,NULL,NULL);
if(status!=CL_SUCCESS)
{
printf("Error:read buffer queue\n");
return EXIT_FAILURE;
}
printf("out:\n");
for(int i=0;i<num*num;i++)
{
printf("%d\t",outbuffer[i]);
if(i%4==3)
printf("\n");
}
status=clReleaseKernel(kernel);
status=clReleaseProgram(program);
status=clReleaseMemObject(outputbuffer);
status=clReleaseCommandQueue(commendQueue);
status=clReleaseContext(context);
free(devices);
delete outbuffer;
system("pause");
return 0;
}
Hello_world.cl
/* Please Write the OpenCL Kernel(s) code here*/
__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;
}
编译 g++ hello_world.cpp -I $AMDAPPSDKROOT/include -L $AMDAPPSDKROOT/lib/x86_64 -lOpenCL -o hello_world
执行 ./hello_world
一、安装build-essential
sudo apt-get install build-essential
如果出现essential包不可用的情况,则sudo apt-get update。更换了软件源就不会出现这个问题了的。
二、安装clblas
下载https://github.com/clMathLibraries/clBLAS
解压
Cd clBLAS-master/src
参考 https://travis-ci.org/clMathLibraries/clBLAS/jobs/128050473#L434
{
export DEBIAN_FRONTEND=noninteractive
git clone --depth=50 --branch=develop https://github.com/clMathLibraries/clBLAS.git clMathLibraries/clBLAS
cd clMathLibraries/clBLAS
export DEBIAN_FRONTEND=noninteractive
sudo -E apt-add-repository -y "ppa:kubuntu-ppa/backports"
sudo -E apt-add-repository -y "ppa:boost-latest/ppa"
sudo -E apt-get -yq update &>> ~/apt-get-update.log
sudo -E apt-get -yq --no-install-suggests --no-install-recommends --force-yes install gfortran cmake libboost-program-options1.55-dev
$ export CLBLAS_ROOT=${TRAVIS_BUILD_DIR}/bin/make/release
$ export OPENCL_REGISTRY=https://www.khronos.org/registry/cl
$ export OPENCL_ROOT=${TRAVIS_BUILD_DIR}/bin/opencl
export CXX=g++
export CC=gcc
mkdir -p ${CLBLAS_ROOT}
pushd ${CLBLAS_ROOT}
cmake -DCMAKE_BUILD_TYPE=Release -DBUILD_TEST=OFF -DBUILD_CLIENT=OFF -DOCL_VERSION=2.0 -DOPENCL_ROOT=${OPENCL_ROOT} ${TRAVIS_BUILD_DIR}/src
make package
}
可能会需要安装Fortran编译器sudo apt-get install gfortran
ACML可能需要
{
下载ACML
http://developer.amd.com/tools-and-sdks/archive/amd-core-math-library-acml/acml-downloads-resources/
安装ACML
tar -zxvf acml-5-3-1-gfortran-64bit.tgz
sudo sh install-acml-5-3-1-gfortran-64bit.sh
}
三、安装opencv
参考:http://www.tuicool.com/articles/nYJrYra
http://docs.opencv.org/3.0-last-rst/doc/tutorials/introduction/linux_install/linux_install.html
3.1 安装opencv所需的库
GCC 4.4.x or later
CMake 2.6 or higher
Git
GTK+2.x or higher, including headers (libgtk2.0-dev)
pkg-config
Python 2.6 or later and Numpy 1.5 or later with developer packages (python-dev, python-numpy)
ffmpeg or libav development packages: libavcodec-dev, libavformat-dev, libswscale-dev
[optional] libtbb2 libtbb-dev
[optional] libdc1394 2.x
[optional] libjpeg-dev, libpng-dev, libtiff-dev, libjasper-dev, libdc1394-22-dev
[compiler] sudo apt-get install build-essential
[required] sudo apt-get install cmake git libgtk2.0-dev pkg-config libavcodec-dev libavformat-dev libswscale-dev
[optional] sudo apt-get install python-dev python-numpy libtbb2 libtbb-dev libjpeg-dev libpng-dev libtiff-dev libjasper-dev libdc1394-22-dev
3.2 官网下载最新的opencv源码
3.3 编译opencv
a.将opencv-3.0.0.zip放在任意目录下,解压 unzip opencv-3.0.0.zip
b.创建编译目录,编译
cd ~/opencv-3.0.0
mkdir release
cd release
%%首次运行下一步的时候出现了问题:提示下载ippicv_linux_20141027.tgz,然后下载不出
%%来,参考:http://my.oschina.net/u/1046919/blog/479947 ,独立下载了该文件,然后替换
%%了原来的文件(原来只有14m,下载的有28m)
%%下载地址 http://sourceforge.net/projects/opencvlibrary/files/3rdparty/ippicv/
%%替换文件路径 ~/opencv-3.0.0/3rdparty/ippicv/downloads/linux-8b449a536a2157bcad08a2b9f266828b
cmake -D CMAKE_BUILD_TYPE=RELEASE -D CMAKE_INSTALL_PREFIX=/usr/local ..
make –j4
%% j后面的数字最好是选择计算机的核心数目
sudo make install
3.4 测试opencv【不必要】
3.4.1 创建工作目录
mkdir ~/opencv-lena
cd ~/opencv-lena
gedit DisplayImage.cpp
3.4.2 编辑如下代码
#include <stdio.h>
#include <opencv2/opencv.hpp>
using namespace cv;
int main(int argc, char** argv )
{
if ( argc != 2 )
{
printf("usage: DisplayImage.out <Image_Path>\n");
return -1;
}
Mat image;
image = imread( argv[1], 1 );
if ( !image.data )
{
printf("No image data \n");
return -1;
}
namedWindow("Display Image", WINDOW_AUTOSIZE );
imshow("Display Image", image);
waitKey(0);
return 0;
}
3.4.3 创建CMake编译文件gedit CMakeLists.txt
写入如下内容:
cmake_minimum_required(VERSION 2.8)
project( DisplayImage )
find_package( OpenCV REQUIRED )
add_executable( DisplayImage DisplayImage.cpp )
target_link_libraries( DisplayImage ${OpenCV_LIBS} )
3.4.4 编译
cd ~/opencv-lena
cmake .(注意后面的 “.” )
make
3.4.5 执行
此时opencv-lena文件夹中已经产生了可执行文件DisplayImage,下载lena.jpg放在opencv-lena下,运行: ./DisplayImage lena.jpg
四 安装其他依赖项
(UBUNTU 14.04用户执行,其他用户去caffe找相关说明)
sudo apt-get install libprotobuf-dev libleveldb-dev libsnappy-dev libopencv-dev libboost-all-dev libhdf5-serial-dev libgflags-dev libgoogle-glog-dev liblmdb-dev protobuf-compiler
五 编译caffe
7.1 完成上述配置,就可以编译caffe了,下载caffe安装包https://github.com/amd/OpenCL-caffe放在任意位置,并解压 unzip OpenCL-caffe-stable.zip
Cd OpenCL-caffe-stable
修改Makefile.config
修改OCL_DIR := /to/OPENCL/path
CLBLAS_DIR := /to/CLBLAS/path
7.3 修改Makefile(不是.config!!!!)
在位置 LIBRARIES += glog gflags protobuf leveldb snappy \
lmdb boost_system hdf5_hl hdf5 m \
opencv_core opencv_highgui opencv_imgproc 处添加opencv_imgcodecs
改为:opencv_core opencv_highgui opencv_imgproc \
opencv_imgcodecs
这一步非常重要,否则编译后会出现错误如下:
CXX/LD -o .build_release/tools/convert_imageset.bin
.build_release/lib/libcaffe.so: undefined reference tocv::imread(cv::String const&, int)'.build_release/lib/libcaffe.so: undefined reference tocv::imencode(cv::String const&, cv::_InputArray const&, std::vector >&, std::vector > const&)'
原因就是opencv3.0.0把imread相关函数放到imgcodecs.lib中了,而非原来的imgproc.lib
7.4 拷贝库
Cd /home/legendluo/ADMAPPSDK/lib/x86_64/sdk
Sudo cp libOpenCL.so.1 /usr/lib
Cd /opt/clBLAS-2.11/lib64
Sudo cp libclBLAS.so.2.11.0 /usr/lib
Cd usr/lib
Sudo ln -s libOpenCL.so.1 libOpenCL.so
Sudo ln -s ibclBLAS.so.2.11.0 ibclBLAS.so
Sudo ln -s ibclBLAS.so.2.11.0 ibclBLAS.so.2
7.5 编译
Sudo make all –j4
Sudo make test
Sudo make runtest
Mkdir log
至此 caffe 已经安装完成。
六 测试caffe (Le-Net 5)
%获取数据
cd data/mnist
sudo sh ./get_mnist.sh %这样是需要下载的,也可以把mnist的数据,下载好然后放在目录下
%重建数据文件,将mnist重建为能被caffe使用的数据格式
cd ~/caffe-master %注意要先回到根目录再进行下面的操作
sudo sh ./examples/mnist/creat_mnist.sh
%训练Le-net 5
%注意如果是使用CPU模式的话,需要修改目录下的lenet_solver.prototxt文件,将
%solver_mode:GPU改为solver_mode:CPU
%在ubuntu 14.04直接双击更改即可,或者在终端用gedit或者vim改
%另外可以把迭代次数改小一点,比如5000
sudo sh ./examples/mnist/train_lenet.sh
七、pycaffe接口配置
8.1 安装依赖库
$ sudo apt-get install python-numpy python-scipy python-matplotlib python-sklearn python-skimage python-h5py python-protobuf python-leveldb python-networkx python-nose python-pandas python-gflags Cython ipython
$ sudo apt-get install protobuf-c-compiler protobuf-compiler
8.2 编译
(要先安装好caffe)
Cd ~/caffe
Make pycaffe
8.3 添加 ~/caffe/python到PYTHONPATH
sudo gedit /etc/profile
# 添加: export PYTHONPATH=/path/to/caffe/python:$PYTHONPATH
$ source /etc/profile # 使之生效
8.4 测试是否可以引用
Python
Import caffe