资讯专栏INFORMATION COLUMN

JOCL 开发

jindong / 2515人阅读

摘要:介绍实际上就是对用语言进行了封装,许多代码都和一样,这一点使得用过的可以非常快的上手,可以到查看源码由于没有指针,所以不得不用来获取地址,这样就感觉其实看起来比还要复杂开发环境搭建参考别人的文章完成开发环境搭建更新显卡驱动安装驱动,应该最新

JOCL 介绍

jocl实际上就是对opencl用java语言进行了封装,许多代码都和opencl一样,这一点使得用过opencl的可以非常快的上手,可以到github查看源码

由于java没有指针,所以jocl不得不用Pointer来获取地址,这样就感觉jocl其实看起来比opencl还要复杂

JOCL 开发环境搭建

参考别人的文章https://my.oschina.net/qutter... 完成jocl开发环境搭建

更新显卡驱动

安装opencl驱动,应该最新版本的显卡驱动都是支持opencl的,可以用 GPU Caps Viewer 来测试,如果没有,AMD的话可以到https://support.amd.com/en-us... 下载驱动

下载opencl sdk

Inter https://software.intel.com/en...

AMD https://developer.amd.com/too...

Nvidia https://developer.nvidia.com/...

下载安装jdk http://www.oracle.com/technet...,不要忘了设置环境变量

下载安装eclipse http://www.eclipse.org/downlo...

下载jar包 http://www.jocl.org/downloads...,需要提取里面的相应jar文件放到项目Referenced Libraries里面,把dll文件放到jdk安装路径/bin下

现在可以直接到官网 http://www.jocl.org/samples/s... 找sample来运行了

封装JOCL

原始的jocl就是对opencl的C语言的重写,是比较麻烦的,下面给出封装代码

PackJocl.java

package jocl;

import static org.jocl.CL.CL_CONTEXT_PLATFORM;
import static org.jocl.CL.CL_DEVICE_TYPE_GPU;
import static org.jocl.CL.CL_MEM_COPY_HOST_PTR;
import static org.jocl.CL.CL_MEM_READ_ONLY;
import static org.jocl.CL.CL_TRUE;
import static org.jocl.CL.clBuildProgram;
import static org.jocl.CL.clCreateBuffer;
import static org.jocl.CL.clCreateCommandQueue;
import static org.jocl.CL.clCreateContext;
import static org.jocl.CL.clCreateKernel;
import static org.jocl.CL.clCreateProgramWithSource;
import static org.jocl.CL.clEnqueueNDRangeKernel;
import static org.jocl.CL.clEnqueueReadBuffer;
import static org.jocl.CL.clGetDeviceIDs;
import static org.jocl.CL.clGetPlatformIDs;
import static org.jocl.CL.clReleaseCommandQueue;
import static org.jocl.CL.clReleaseContext;
import static org.jocl.CL.clReleaseKernel;
import static org.jocl.CL.clReleaseMemObject;
import static org.jocl.CL.clReleaseProgram;
import static org.jocl.CL.clSetKernelArg;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;

import org.jocl.CL;
import org.jocl.Pointer;
import org.jocl.Sizeof;
import org.jocl.cl_command_queue;
import org.jocl.cl_context;
import org.jocl.cl_context_properties;
import org.jocl.cl_device_id;
import org.jocl.cl_kernel;
import org.jocl.cl_mem;
import org.jocl.cl_platform_id;
import org.jocl.cl_program;

/**
 * A small JOCL sample.
 */
public class PackJocl
{
    cl_context context;                // 上下文
    cl_command_queue commandQueue;    // 命令队列
    cl_program program;                // 程序对象
    cl_kernel kernel;                // Kernel对象
    cl_mem memObjects[];            // 内存对象数组
    
    /**
     * 读取文件的内容
     * @param file 想要读取的文件对象
     * @return 返回文件内容
     */
    public static String readCl(File file){
        StringBuilder result = new StringBuilder();
        try{
            BufferedReader br = new BufferedReader(new FileReader(file));//构造一个BufferedReader类来读取文件
            String s = null;
            while((s = br.readLine())!=null){//使用readLine方法,一次读一行
                result.append(System.lineSeparator()+s);
            }
            br.close();    
        }catch(Exception e){
            e.printStackTrace();
        }
        return result.toString();
    }
    
    PackJocl(){
        
    }
    
    /**
     * 加载平台和驱动
     * @param platformIdx 平台index
     * @param deviceIdx 驱动index
     */
    @SuppressWarnings("deprecation")
    public void init(int platformIdx, int deviceIdx){
        final int platformIndex = platformIdx; // 选择哪个平台
        final long deviceType = CL_DEVICE_TYPE_GPU;
        final int deviceIndex = deviceIdx;

        // Enable exceptions and subsequently omit error checks in this sample
        CL.setExceptionsEnabled(true);

        // Obtain the number of platforms
        int numPlatformsArray[] = new int[1];
        clGetPlatformIDs(0, null, numPlatformsArray);
        int numPlatforms = numPlatformsArray[0];

        // Obtain a platform ID
        cl_platform_id platforms[] = new cl_platform_id[numPlatforms];
        clGetPlatformIDs(platforms.length, platforms, null);
        cl_platform_id platform = platforms[platformIndex];

        // Initialize the context properties
        cl_context_properties contextProperties = new cl_context_properties();
        contextProperties.addProperty(CL_CONTEXT_PLATFORM, platform);
        
        // Obtain the number of devices for the platform
        int numDevicesArray[] = new int[1];
        clGetDeviceIDs(platform, deviceType, 0, null, numDevicesArray);
        int numDevices = numDevicesArray[0];
        
        // Obtain a device ID 
        cl_device_id devices[] = new cl_device_id[numDevices];
        clGetDeviceIDs(platform, deviceType, numDevices, devices, null);
        cl_device_id device = devices[deviceIndex];
        context = clCreateContext(
        contextProperties, 1, new cl_device_id[]{device}, 
        null, null, null);
    
        // Create a command-queue for the selected device
        commandQueue = clCreateCommandQueue(context, device, 0, null);
    }
    
    /**
     * 创建Kernel
     * @param clName Kernel文件名
     * @param funcName Kernel函数名
     */
    public void createKernel(String clName, String funcName){
        program = clCreateProgramWithSource(context, 1, new String[]{  readCl(new File(clName)) }, null, null);
        
        // Build the program
        clBuildProgram(program, 0, null, null, null, null);
            
        // Create the kernel
        kernel = clCreateKernel(program, funcName, null);
    }
    
    /**
     * 创建Kernel
     * @param p 包含所有参数的指针数组
     * @param n 分配内存空间大小 
     */
    public void setParameters(Pointer[] p, int n){
        memObjects = new cl_mem[p.length];
        for(int i = 0; i < p.length; i++){
            memObjects[i] = clCreateBuffer(context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, Sizeof.cl_float * n, p[i], null);
        }
        
        for(int i = 0; i < p.length; i++){
            clSetKernelArg(kernel, i, Sizeof.cl_mem, Pointer.to(memObjects[i]));
        }
        
    }
    
    /**
     * 执行Kernel
     * @param dim 维数
     * @param global_work_size[] global_work_size
     * @param local_work_size[] local_work_size
     */
    public void execute(int dim, long global_work_size[], long local_work_size[]){
         // Execute the kernel
         clEnqueueNDRangeKernel(commandQueue, kernel, dim, null,global_work_size, local_work_size, 0, null, null);
    }

    /**
     * 把显存里的计算结果取回内存
     * @param index 参数位置
     * @param dstPointer 结果指针
     * @param size 分配内存空间大小 
     */
    public void getData(int index, Pointer dstPointer, int size){
         clEnqueueReadBuffer(commandQueue, memObjects[index], CL_TRUE, 0, size * Sizeof.cl_float, dstPointer, 0, null, null);
    }
    
    public void clear(){
         clReleaseMemObject(memObjects[0]);
         clReleaseMemObject(memObjects[1]);
         clReleaseMemObject(memObjects[2]);
         clReleaseKernel(kernel);
         clReleaseProgram(program);
         clReleaseCommandQueue(commandQueue);
         clReleaseContext(context);
    }
  
}

PackageTest.java

package jocl;

import org.jocl.Pointer;

public class PackageTest {
    public static void main(String args[]){
        PackJocl  jocl= new PackJocl();
        
        // 初始化,第一个参数是平台index,第二个参数是驱动index
        jocl.init(1,0);
        
        // 创建内核, 第一个是内核文件名,第二个是内核函数名
        jocl.createKernel("E://kernel.cl", "add");
        
        // 获取测试数据并复制到显存
        int n = 10;
        float srcArrayA[] = new float[n];
        float srcArrayB[] = new float[n];
        float dstArray[] = new float[n];
        for (int i=0; i

kernel.cl 我是放在E盘根目录下,所以PackageTest.java中写的jocl.createKernel("E://kernel.cl", "add"); 你可以改成其他的

__kernel void add(__global const float *a, __global const float *b, __global float *c)
{
    int gid = get_global_id(0);
    printf("%d	",gid);
    c[gid] = a[gid] + b[gid];
}

运行结果

第一次写文章,希望可以帮助到你

本文同步更新我的个人博客https://blog.yjqing.xin/jocl

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/76459.html

相关文章

  • 小程序 · 云开发

    摘要:课程内容以打造一款拥有天气预报和签到功能的小程序为主线,从基础知识到小程序运行机制,从开发环境搭建到小程序云开发的接口使用调试上线,打通微信小程序开发全流程。 9 月 11 日,微信开发者工具新增小程序「云开发」功能。 showImg(https://segmentfault.com/img/bVbjQLW?w=1000&h=544); 大多数开发者在开发应用时和部署服务时,无论是选择...

    nanchen2251 评论0 收藏0
  • 混合式app开发框架

    摘要:混合式开发做出的手机应用无论在性能还是易用性方面都很接近原生应用。下面介绍几个流行的混合式开发框架。相比于其他开发框架,更加轻量,体积小巧。 目前混合式开发已经逐渐成熟,混合式app开发只需要要求开发者会使用css和js前端代码就可以实现手机app应用的开发,而不需要再去学习安卓或苹果开发,降低了app开发的门槛。混合式开发做出的手机应用无论在性能还是易用性方面都很接近原生app应用。...

    hot_pot_Leo 评论0 收藏0
  • 混合式app开发框架

    摘要:混合式开发做出的手机应用无论在性能还是易用性方面都很接近原生应用。下面介绍几个流行的混合式开发框架。相比于其他开发框架,更加轻量,体积小巧。 目前混合式开发已经逐渐成熟,混合式app开发只需要要求开发者会使用css和js前端代码就可以实现手机app应用的开发,而不需要再去学习安卓或苹果开发,降低了app开发的门槛。混合式开发做出的手机应用无论在性能还是易用性方面都很接近原生app应用。...

    darkbug 评论0 收藏0
  • 原生开发、H5开发和混合开发的区别

    摘要:目前市场上主流的分为三种原生即和混合三种,相对应的定制开发就是原生开发开发和混合开发。三混合原生开发混合开发开发,是指在开发一款产品的时候,为了提高效率节省成本而利用原生与的开发技术的混合应用。 目前市场上主流的APP分为三种:原生APP、Web APP(即HTML5)和混合APP三种,相对应的定 制开发就是原生开发、H5开发和混合开发。那么这三种开发模式究竟有何不同呢?...

    褰辩话 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<