当前位置: 首页 > 工具软件 > OpenCL Caffe > 使用案例 >

ubuntu14.04 amd显卡 OpenCL caffe安装

沈曜灿
2023-12-01


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)//若有平台的话

{

//为平台分派numPlatformssizeof(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);//填充OUTBUFFER0

 

//创建缓存对象

//第一个参数是有效的上下文,第二个参数是用来指定分派和使用信息。,第三个参数是所分派缓存对象的字节数

//第四个参数指向有应用所分派的缓存数据,第五个是返回错误类型。

 

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

//第五个参数全局工作组数目,第六个是局部工作组数目,第789个是设置内核执行前的等待事件。

 

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


caffe安装

一、安装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.0imread相关函数放到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/pythonPYTHONPATH  

sudo gedit /etc/profile

# 添加: export PYTHONPATH=/path/to/caffe/python:$PYTHONPATH

$ source /etc/profile # 使之生效

8.4 测试是否可以引用

Python

Import caffe




 类似资料: