`
gashero
  • 浏览: 963228 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

OpenCL与GPU计算入门 译文

阅读更多

OpenCL与GPU计算入门

作者:

Erik Smistad

译者:

gashero

日期:

2015-05-26

标题原文:

Getting started with OpenCL and GPU Computing

地址:

http://www.thebigblob.com/getting-started-with-opencl-and-gpu-computing/

目录

  • 1   安装和设置OpenCL
    • 1.1   在Ubuntu Linux上安装AMD显卡上的OpenCL
    • 1.2   在Ubuntu Linux上安装nVidia显卡上的OpenCL
  • 2   第一个OpenCL程序,向量加法
    • 2.1   内核
    • 2.2   主机程序
  • 3   编译OpenCL程序
  • 4   学习更多

OpenCL(Open Computing Language,开放计算语言)是一个在并行多计算平台上写程序的框架,由多个制造商提供多种计算设备,如AMD、Intel、ATI、nVidia等。这个框架定义了一种语言来编写内核(kernel)。这些内核是一些运行在不同计算设备上的函数。本文解释如何开始OpenCL,以及两个列表并行求和的例子。

1   安装和设置OpenCL

最初需要下载最新的显卡驱动,这因为如果OpenCL在你的显卡驱动不支持OpenCL时无法工作。

要安装OpenCL,你需要下载一个OpenCL实现。主要的显卡制造商nVidia和AMD/ATI都有提供基于GPU的OpenCL实现。这些实现都提供了SDK和有用的工具,如性能优化器。下一步是下载和安装GPU SDK。注意不是所有的显卡都支持,支持的显卡参见制造商网站。

对AMD/ATI,下载 http://developer.amd.com/sdks/AMDAPPSDK/Pages/default.aspx

对nVidia,下载 http://developer.nvidia.com/object/cuda_download.html

安装步骤依赖于SDK和OS。遵循如下步骤。推荐使用Ubuntu Linux和AMD 7970显卡。

1.1   在Ubuntu Linux上安装AMD显卡上的OpenCL

要安装最新的AMD驱动到Ubuntu-12.04,需要安装和激活"ATI/AMD proprietary FGLRX显卡驱动"。

再这一步完成后,下载和解压 http://developer.amd.com/sdks/AMDAPPSDK/Pages/default.aspx

AMD APP SDK 2.8包含了安装器,运行:

sudo sh Install-AMD-APP.sh

下一步,安装OpenCL头文件:

sudo apt-get install opencl-headers

这就行了,注意AMD APP SDK,及其例子在 /opt/AMDAPP

1.2   在Ubuntu Linux上安装nVidia显卡上的OpenCL

下载CUDA SDK http://developer.nvidia.com/object/cuda_download.html 。打开终端运行安装文件:

sudo sh cudatoolkit_3.1_linux_64_ubuntu9.10.run

下载开发者驱动,安装前关闭X,运行文件然后开启X。其中关闭X用:

sudo /etc/init.d/gdm stop

然后打开终端通过Ctrl+Alt+F5,登录并导航到下载驱动的目录:

sudo sh devdriver_3.1_linux_64_256.40.run

之后重启X:

startx

在开始编译OpenCL应用前,需要添加库的路径:

export LD_LIBRARY_PATH=/usr/local/cuda/lib64

2   第一个OpenCL程序,向量加法

展示OpenCL的简单例子。假设有2个列表的数字,A和B,相同长度。向量加法就是将A和B对应的每个像素相加,并将结果放入新的列表C。

通过循环方式的如下:

for (int i=0; i<LIST_SIZE; i++) {

    C[i]=A[i]+B[i];

}

这个算法简单,但是是线性时间复杂度的,O(n)是列表大小。因为每次迭代都是独立的,因此操作是数据并行的,意味着每次迭代可以同时计算。所以我们有n个核心的处理器用以在常量时间内完成计算O(1)。

要编写OpenCL内核来并行计算。内核是一个函数,运行在计算设备上。

2.1   内核

内核以OpenCL语言编写,是C的子集,以及包含了很多数学和向量函数。内核做向量加法如下:

__kernel void vector_add(__global const int *A, __global const int *B, __global int *C) {

    //获得当前要处理元素的索引

    int i=get_global_id(0);

    //做计算

    C[i]=A[i]+B[i];

}

2.2   主机程序

主机程序控制了内核的执行。主机程序以C语言编写,但可以绑定到其他语言如C++和Python。OpenCL API定义于 cl.h (Apple为 opencl.h )。如下代码为主机程序执行了如上的内核。不会讲解细节,具体参见介绍性的 "The OpenCL Programming Book" 。主机程序的主要步骤:

  1. 获取平台和设备的信息
  2. 选择设备用以执行
  3. 创建OpenCL上下文
  4. 创建命令队列
  5. 创建内存缓冲对象
  6. 传输数据到设备的内存缓冲
  7. 创建程序对象
  8. 载入内核源码,并编译,或载入预编译的二进制OpenCL程序
  9. 创建内核对象
  10. 设置内核参数
  11. 执行内核
  12. 读取内存对象,此时从计算设备读取C列表

#include <stdio.h>

#include <stdlib.h>

 

#ifdef __APPLE__

#include <OpenCL/opencl.h>

#else

#include <CL/cl.h>

#endif

 

#define MAX_SOURCE_SIZE (0x100000)

 

int main(void) {

    //创建2个输入向量

    int i;

    cosnt int LIST_SIZE=1024;

    int *A=(int*)malloc(sizeof(int)*LIST_SIZE);

    int *B=(int*)malloc(sizeof(int)*LIST_SIZE);

    for (i=0; i<LIST_SIZE; i++) {

        A[i]=i;

        B[i]=LIST_SIZE-i;

    }

 

    //载入内核源码到source_str

    FILE *fp;

    char *source_str;

    size_t source_size;

 

    fp=fopen("vector_add_kernel.cl","r");

    if (!fp) {

        fprintf(stderr, "Failed to load kernel\n");

        exit(1);

    }

    source_str=(char*)malloc(MAX_SOURCE_SIZE);

    source_size=fread(source_str,1,MAX_SOURCE_SIZE,fp);

    fclose(fp);

 

    //获得平台和设备信息

    cl_platform_id platform_id=NULL;

    cl_device_id device_id=NULL;

    cl_uint ret_num_devices;

    cl_uint ret_num_platforms;

    cl_int ret=clGetPlatformIDs(1, &platform_id, &ret_num_platform);

    ret=clGetDeviceIDs(platform_id, CL_DEVICE_TYPE_DEFAULT, 1, &deivce_id, &ret_num_devices);

 

    //创建OpenCL上下文

    cl_context context=clCreateContext(NULL,1,&device_id,NULL,NULL,&ret);

    //创建命令队列

    cl_command_queue command_queue=clCreateCommandQueue(context,device_id,0,&ret);

    //创建内存缓冲对象,在设备上为每个向量

    cl_mem a_mem_obj=clCreateBuffer(context,CL_MEM_READ_ONLY,

            LIST_SIZE*sizeof(int),NULL,&ret);

    cl_mem b_mem_obj=clCreateBuffer(context,CL_MEM_READ_ONLY,

            LIST_SIZE*sizeof(int),NULL,&ret);

    cl_mem c_mem_obj=clCreateBuffer(context,CL_MEM_WRITE_ONLY,

            LIST_SIZE*sizeof(int),NULL,&ret);

 

    //拷贝数据A和B到对应的内存缓冲

    ret=clEnqueueWriteBuffer(command_queue,a_mem_obj,CL_TRUE,0,

            LIST_SIZE*sizeof(int),A,0,NULL,NULL);

    ret=clEnqueueWriteBuffer(command_queue,a_mem_obj,CL_TRUE,0,

            LIST_SIZE*sizeof(int),B,0,NULL,NULL);

 

    //创建程序

    cl_program program=clCreateProgramWithSource(context,1,

            (const char**)&source_str,(const size_t*)&source_size, &ret);

    //构建程序

    ret=clBuildProgram(program,1,&device_id,NULL,NULL,NULL);

    //创建OpenCL内核

    cl_kernel kernel=clCreateKernel(program,"vector_add",&ret);

 

    //设置内核参数

    ret=clSetKernelArg(kernel,0,sizeof(cl_meme),(void*)&a_mem_obj);

    ret=clSetKernelArg(kernel,1,sizeof(cl_meme),(void*)&b_mem_obj);

    ret=clSetKernelArg(kernel,2,sizeof(cl_meme),(void*)&c_mem_obj);

 

    //执行内核

    size_t global_item_size=LIST_SIZE;  //处理整个列表

    size_t local_item_size=64;          //分割为64个组

    ret=clEnqueueNDRangeKernel(command_queue,kernel,1,NULL,

            &global_item_size,&local_item_size,0,NULL,NULL);

 

    //读取内存缓冲C到本地变量C

    int *C=(int*)malloc(sizeof(int)*LIST_SIZE);

    ret=clEnqueueReadBuffer(command_queue,c_mem_obj,CL_TRUE,0,

        LIST_SIZE*sizeof(int),C,0,NULL,NULL);

 

    //显示结果

    for (i=0; i<LIST_SIZE; i++) {

        printf("%d + %d = %d\n", A[i], B[i], C[i]);

    }

 

    //清理资源

    ret=clFlush(command_queue);

    ret=clFinish(command_queue);

    ret=clReleaseKernel(kernel);

    ret=clReleaseProgram(program);

    ret=clReleaseMemObj(a_mem_obj);

    ret=clReleaseMemObj(b_mem_obj);

    ret=clReleaseMemObj(c_mem_obj);

    ret=clReleaseCommandQueue(command_queue);

    ret=clReleaseContext(context);

    free(A);

    free(B);

    free(C);

    return 0;

}

想要OpenCL运行在GPU上,你需要修改常量 CL_DEVICE_TYPE_DEFAULTCL_DEVICE_TYPE_GPU 。要运行在CPU上修改为 CL_DEVICE_TYPE_CPU 。所以修改很简单。

3   编译OpenCL程序

如果OpenCL头文件和库放在了正确的位置,如下命令编译向量加法程序:

gcc main.o -o vectorAddition -l OpenCL

4   学习更多

要学习更多关于OpenCL,建议从 "The OpenCL programming book" 开始。如下是其他的OpenCL信息:

  1. nVidia's page on OpenCL: http://www.nvidia.com/object/cuda_opencl_new.html
  2. AMD/ATI's page on OpenCL: http://developer.amd.com/zones/OpenCLZone/Pages/default.aspx
  3. Official website of OpenCL: http://www.khronos.org/opencl/
1
0
分享到:
评论

相关推荐

    opencl调用gpu资源进行加速算法实现例子

    OpenCL(Open Computing Language)是一种开放标准,用于访问并行计算资源,如GPU(图形处理器)、CPU和其他硬件加速器。这个“opencl调用gpu资源进行加速算法实现例子”是针对如何利用OpenCL来编写核函数,从而有效...

    CUDA助力OpenCL GPU并行计算无处不在

    CUDA助力OpenCL GPU并行计算无处不在 本文将详细介绍CUDA和OpenCL的基本概念,并探讨它们在GPU并行计算方面的应用。 CUDA是什么? CUDA(Compute Unified Device Architecture)是NVIDIA公司推出的一个通用计算...

    OpenCL异构并行计算随书源码

    本随书源码包提供了深入学习OpenCL异构并行计算原理、机制与优化实践的实例。 1. **异构计算**:异构计算是指在单一系统中结合不同类型的处理器,如CPU和GPU,以协同处理不同的计算任务。OpenCL通过其API允许开发者...

    opencl 多gpu矩阵数组运算

    OpenCL(Open Computing Language)是一种开放源代码的并行编程框架,主要应用于异构计算,如CPU、GPU、FPGA等设备。它提供了一种跨平台的方式来开发高性能计算的应用程序,尤其是在图形处理和大规模数据计算方面...

    gpu.rar_OpencL_opencl gpu

    学习和使用OpenCL,你需要理解并行计算的概念,掌握如何编写内核代码,以及如何通过主机代码与GPU通信。OpenCL的强大在于其灵活性和广泛的支持,但这也意味着开发者需要对目标硬件有一定的理解和优化技巧,以充分...

    clrx_OpencL_GPU_汇编_amd_

    这个标题指的是一个与OpenCL相关的资源,特别强调了GPU(图形处理器)的汇编编程和AMD平台的使用。"clrx"可能是指AMD的OpenCL SDK的一个组件或者一个特定的开发工具,它允许开发者利用AMD GPU的计算能力,通过汇编...

    Debugging OpenCL Kernels on GPU

    在调试 OpenCL 核心时,target 机器不能与 host 机器相同,因为 GPU 需要在 target 机器上运行。target 机器可以是任何具有 Intel® Core™ 处理器的机器,运行支持的 Windows* 操作系统。 OpenCL™ GPU Kernel ...

    opencl异构并行计算随书源码

    OpenCL(Open Computing Language)是一种开放标准,用于跨多种处理器架构进行异构并行计算,包括CPU、GPU、FPGA以及ASIC等硬件。这个“opencl异构并行计算随书源码”提供了与《OpenCL异构并行计算第二版》教材配套...

    CUDA助力OpenCL_GPU并行计算无处不在

    众所周知,NVIDIA是GPU的通用计算技术先驱者,它的CUDA架构产品深入人心。而在通用计算的API层面不止NVIDIA一家独秀,Apple(苹果)公司主导的OpenCL也赢得了业界同行的大力支持,当然NVIDIA也是OpenCL的核心成员之...

    OpenCL中文入门完整教程

    ### OpenCL中文入门完整教程知识点总结 #### 一、并行计算概述 ##### 1.1 并行计算概述 并行计算是指将一个复杂的计算任务分解为多个可同时处理的子任务,利用多处理器或多核心处理器等硬件资源来加速计算过程。...

    MIOpenGEMM_OpencL_GPU_GEMM_amd_

    总结起来,MIOpenGEMM是AMD GPU优化OpenCL GEMM运算的重要库,通过高效利用GPU并行计算能力,提升了深度学习计算的性能。对于希望在AMD GPU平台上进行深度学习开发的程序员来说,理解和掌握MIOpenGEMM的原理和使用...

    opencl异构并行计算原理机制与优化实践 完整 pdf

    opencl异构并行计算原理机制与优化实践 完整 pdf

    OpenCL GPU性能测试源代码

    OpenCL,全称为“Open Computing Language”,是一种开放式的并行计算框架,主要设计用于利用GPU(图形处理器)和其他多核处理器进行高性能计算。OpenCL提供了跨平台的编程接口,允许开发者编写程序,使得数据能够在...

    支持OpenCL的GPU加速人工神经网络训练

    例如,RPROP算法在GPU上的OpenCL实现能够利用其并行计算能力,对神经网络中的权重进行高效的更新,从而加速整个训练过程。 研究将人工神经网络训练算法(如RPROP)通过OpenCL语言实现并运行在GPU上,不仅能够提升...

    cpp-Libclsph基于OpenCL的GPU加速SPH流体仿真库

    1. **并行计算**:Libclsph利用OpenCL的并行计算能力,将复杂的SPH计算任务拆分为多个子任务,同时在多核GPU上执行,显著提高了计算速度。 2. **GPU优化**:经过专门优化,Libclsph能够充分利用GPU的浮点运算能力,...

    支持OpenCL的GPU加速人工神经网络训练.pdf

    OpenCL是一个基于C语言的并行计算平台,可以使用GPU、CPU等多种设备进行计算。通过使用OpenCL,可以将人工神经网络训练算法实现到GPU上,以提高训练速度。 实验结果表明,使用OpenCL实现的GPU加速人工神经网络训练...

    基于OpenCL的多GPU并行计算的研究与应用1

    【基于OpenCL的多GPU并行计算的研究与应用】 OpenCL(Open Computing Language)是一种开放标准,用于编写在异构计算环境中运行的程序,包括CPU、GPU和其他类型的处理器。随着计算机处理器从单核到多核时代的演进,...

    OpenCL为GPU推波助澜.pdf

    OpenCL为GPU推波助澜.pdf

    opencl GPU加速rgb24与yuv444p格式相互转换核函数参考

    总之,OpenCL为GPU加速RGB24与YUV444P之间的颜色空间转换提供了一个强大而灵活的框架。通过编写并行执行的内核函数,我们可以充分利用GPU的计算资源,实现高效的图像和视频处理。在代码压缩包中,"code"文件可能包含...

Global site tag (gtag.js) - Google Analytics