使用NVIDIA Nsight Tegra建立OpenCL项目

本文的主要内容是使用NVIDIA提供的Nsight Tegra软件建立OpenCL项目,测试设备为Nexus 7 2013 WiFi版(Android 4.4.4)。

主要参考的资料为“高通平台下安卓opencl小例子”[1],“基于 Android* 操作系统的 OpenCL™ 入门”[2]

写这篇文章的目的是因为资料[1]中使用的是Eclipse作为开发工具,而用Eclipse+NDK开发感觉调试时不是很方便,而用集成在Visual Studio中的Nsight Tegra调试还是比较方便的。而且[1]中的OpenCL代码是写在C源文件中的,如果.cl文件内容较多时,看起来比较奇怪。

1.需要准备的工具软件(我现在正在使用的版本)

  • Visual Studio 2013
  • NVIDIA® Nsight™ Tegra®, Visual Studio Edition 3.0
  • Android NDK r10e
  • AdrenoSDK
  • libOpenCL.so

其中AdrenoSDK需要在高通的官方网站下载,实际上只需要用到里面的几个CL头文件,文章末尾会提供下载,这样就不需要下载AdrenoSDK了;libOpenCL.so需要在你用adb pull命令从自己的测试设备上提取到PC机上。例如.so文件在/system/vendor/lib/目录下,就在PC上的命令行里面运行 adb pull /system/vendor/lib/libOpenCL.so 就好了[1]

2.具体步骤

各种软件的安装就不在赘述了。

新建项目,如图所示,选择Hello World Demo。

先生成一下项目,如果出现下面这样的错误,那就是Target API Level设置有误,因为我的Nexus 7的系统是4.4.4,所以选android-19。

在项目属性页面设置修改“Min Android API Level”和“Target Android API Level”。

xml文件里面也要修改。

这样就可以看到Hello World Demo编译成功的消息了。如果还有其它错误就根据输出的错误信息自行检查一下吧。

看到Demo编译成功,就可以进行下一步的操作了。

首先,如图所示,在项目文件夹下面添加include和lib文件夹,把CL文件夹(文章末尾会提供下载)复制到include里,把libOpenCL.so复制到lib里。

这样做的目的是后面可以使用到相对路径。然后在项目属性里面分别修改如下几个地方(主要就是引用OpenCL的头文件和库文件)。

添加完后重新生成一下,无错误就可以继续下去。

修改HelloJni.java的内容如下。

  1 /*
  2  * Copyright (C) 2009 The Android Open Source Project
  3  *
  4  * Licensed under the Apache License, Version 2.0 (the "License");
  5  * you may not use this file except in compliance with the License.
  6  * You may obtain a copy of the License at
  7  *
  8  *      http://www.apache.org/licenses/LICENSE-2.0
  9  *
 10  * Unless required by applicable law or agreed to in writing, software
 11  * distributed under the License is distributed on an "AS IS" BASIS,
 12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 13  * See the License for the specific language governing permissions and
 14  * limitations under the License.
 15  */
 16 package com.example.hellojni;
 17
 18 import java.io.BufferedReader;
 19 import java.io.IOException;
 20 import java.io.InputStream;
 21 import java.io.InputStreamReader;
 22
 23 import android.app.Activity;
 24 import android.widget.TextView;
 25 import android.os.Bundle;
 26
 27 public class HelloJni extends Activity
 28 {
 29     private TextView tv;
 30
 31     /** Called when the activity is first created. */
 32     @Override
 33     public void onCreate(Bundle savedInstanceState)
 34     {
 35         super.onCreate(savedInstanceState);
 36
 37         /*
 38          * Create a TextView and set its content. the text is retrieved by
 39          * calling a native function.
 40          */
 41         tv = new TextView(this);
 42         tv.setText(initOpenCL(getOpenCLProgram()));
 43         setContentView(tv);
 44     }
 45
 46     private String getOpenCLProgram()
 47     {
 48         /*
 49          * OpenCL program text is stored in a separate file in assets directory.
 50          * Here you need to load it as a single string.
 51          *
 52          * In fact, the program may be directly built into native source code
 53          * where OpenCL API is used, it is useful for short kernels (few lines)
 54          * because it doesn‘t involve loading code and you don‘t need to pass it
 55          * from Java to native side.
 56          */
 57
 58         try
 59         {
 60             StringBuilder buffer = new StringBuilder();
 61             InputStream stream = getAssets().open("step.cl");
 62             BufferedReader reader = new BufferedReader(new InputStreamReader(
 63                         stream));
 64             String s;
 65
 66             while ((s = reader.readLine()) != null)
 67             {
 68                 buffer.append(s);
 69                 buffer.append("\n");
 70             }
 71
 72             reader.close();
 73             return buffer.toString();
 74         }
 75         catch (IOException e)
 76         {
 77             e.printStackTrace();
 78         }
 79         return "";
 80
 81     }
 82
 83     /*
 84      * A native method that is implemented by the ‘Android4‘ native library,
 85      * which is packaged with this application.
 86      */
 87
 88     /*
 89      * This is another native method declaration that is *not* implemented by
 90      * ‘Android4‘. This is simply to show that you can declare as many native
 91      * methods in your Java code as you want, their implementation is searched
 92      * in the currently loaded native libraries only the first time you call
 93      * them.
 94      *
 95      * Trying to call this function will result in a
 96      * java.lang.UnsatisfiedLinkError exception !
 97      */
 98
 99     private native String initOpenCL(String openCLProgramText);
100
101     public native String testOpenCL();
102
103     public native String getPlatformName();
104
105     public native String getDeviceName();
106
107     /*
108      * this is used to load the ‘Android4‘ library on application startup. The
109      * library has already been unpacked into
110      * /data/data/com.example.HelloJni/lib/libAndroid4.so at installation time
111      * by the package manager.
112      */
113     static
114     {
115         System.loadLibrary("AndroidOpenCL");
116     }
117 }

HelloJni.java

在jni文件夹下面添加HelloJni.h,内容如下。

 1 /* DO NOT EDIT THIS FILE - it is machine generated */
 2 #include <jni.h>
 3 /* Header for class com_example_ocl_MainActivity */
 4
 5 #ifndef HelloJni
 6 #define HelloJni
 7 #ifdef __cplusplus
 8 extern "C" {
 9 #endif
10     /*
11     * Class:     com_example_ocl_MainActivity
12     * Method:    testopencl
13     * Signature: ()Ljava/lang/String;
14     */
15     JNIEXPORT jstring JNICALL Java_com_example_hellojni_HelloJni_testOpenCL(
16         JNIEnv *, jobject);
17
18     /*
19     * Class:     com_example_ocl_MainActivity
20     * Method:    getPlatformName
21     * Signature: ()Ljava/lang/String;
22     */
23     JNIEXPORT jstring JNICALL Java_com_example_hellojni_HelloJni_getPlatformName(
24         JNIEnv *, jobject);
25
26     /*
27     * Class:     com_example_ocl_MainActivity
28     * Method:    getDeviceName
29     * Signature: ()Ljava/lang/String;
30     */
31     JNIEXPORT jstring JNICALL Java_com_example_hellojni_HelloJni_getDeviceName(
32         JNIEnv *, jobject);
33
34     JNIEXPORT jstring JNICALL Java_com_example_hellojni_HelloJni_initOpenCL(
35         JNIEnv *, jobject, jstring openCLProgramText);
36
37 #ifdef __cplusplus
38 }
39 #endif
40 #endif
41 void Init_OpenCL();
42 void Context_cmd();
43 void Create_Buffer(int *data);
44 void Create_program();
45 void Set_arg();
46 void Execution();
47 void CopyOutResult(int*out);

HelloJni.h

修改HelloJni.cpp的内容如下。

  1 #include <stdio.h>
  2 #include <string.h>
  3 #include <jni.h>
  4 #include <CL/cl.h>
  5 #include <malloc.h>
  6 #include <stdlib.h>
  7 #include "HelloJni.h"
  8
  9 #define LEN(arr) sizeof(arr) / sizeof(arr[0])
 10 #define N 1024
 11 #define NUM_THREAD 128
 12
 13 cl_uint num_device;
 14 cl_uint num_platform;
 15 cl_platform_id *platform;
 16 cl_device_id *devices;
 17 cl_int err;
 18 cl_context context;
 19 cl_command_queue cmdQueue;
 20 cl_mem buffer, sum_buffer;
 21 cl_program program;
 22 cl_kernel kernel;
 23 char src[10240];
 24 int num_block;
 25
 26 int test()
 27 {
 28     int* in, *out;
 29     num_block = N / NUM_THREAD;
 30     in = (int*)malloc(sizeof(int) * N);
 31     out = (int*)malloc(sizeof(int) * num_block);
 32     for (int i = 0; i < N; i++)
 33     {
 34         in[i] = 1;
 35     }
 36     Init_OpenCL();
 37     Context_cmd();
 38     Create_Buffer(in);
 39     Create_program();
 40     Set_arg();
 41     Execution();
 42     CopyOutResult(out);
 43     int sum = 0;
 44     for (int i = 0; i < num_block; i++)
 45     {
 46         sum += out[i];
 47     }
 48     return sum;
 49 }
 50 /* This is a trivial JNI example where we use a native method
 51 * to return a new VM String. See the corresponding Java source
 52 */
 53 extern "C"
 54 JNIEXPORT jstring JNICALL
 55 Java_com_example_hellojni_HelloJni_testOpenCL(JNIEnv* env, jobject thiz)
 56 {
 57     char result[10];
 58     sprintf(result, "%d\n", test());
 59     return env->NewStringUTF(result);
 60 }
 61
 62 extern "C"
 63 JNIEXPORT jstring JNICALL
 64 Java_com_example_hellojni_HelloJni_getPlatformName(JNIEnv* env, jobject thiz)
 65 {
 66     char buffer[1024];
 67     clGetPlatformInfo(platform[0], CL_PLATFORM_NAME, sizeof(buffer), buffer,
 68         NULL);
 69     return env->NewStringUTF(buffer);
 70 }
 71
 72 extern "C"
 73 JNIEXPORT jstring JNICALL
 74 Java_com_example_hellojni_HelloJni_getDeviceName(JNIEnv* env, jobject thiz)
 75 {
 76     char buffer[1024];
 77     clGetDeviceInfo(devices[0], CL_DEVICE_NAME, sizeof(buffer), buffer, NULL);
 78     return env->NewStringUTF(buffer);
 79 }
 80
 81 extern "C"
 82 JNIEXPORT jstring JNICALL
 83 Java_com_example_hellojni_HelloJni_initOpenCL(JNIEnv* env, jobject thiz,
 84 jstring openCLProgramText)
 85 {
 86     const char* openCLProgramTextNative = env->GetStringUTFChars(
 87         openCLProgramText, 0);
 88     strcpy(src, openCLProgramTextNative);
 89     char result[10];
 90     sprintf(result, "%d\n", test());
 91     return env->NewStringUTF(result);
 92 }
 93
 94 void Init_OpenCL()
 95 {
 96     size_t nameLen1;
 97     char platformName[1024];
 98
 99     err = clGetPlatformIDs(0, 0, &num_platform);
100     platform = (cl_platform_id*)malloc(sizeof(cl_platform_id) * num_platform);
101     err = clGetPlatformIDs(num_platform, platform, NULL);
102
103     err = clGetDeviceIDs(platform[0], CL_DEVICE_TYPE_GPU, 0, NULL, &num_device);
104     devices = (cl_device_id*)malloc(sizeof(cl_device_id) * num_device);
105     err = clGetDeviceIDs(platform[0], CL_DEVICE_TYPE_GPU, num_device, devices,
106         NULL);
107
108 }
109
110 void Context_cmd()
111 {
112     context = clCreateContext(NULL, num_device, devices, NULL, NULL, &err);
113     cmdQueue = clCreateCommandQueue(context, devices[0], 0, &err);
114 }
115
116 void Create_Buffer(int *data)
117 {
118
119     buffer = clCreateBuffer(context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR,
120         sizeof(int) * N, data, &err);
121     sum_buffer = clCreateBuffer(context, CL_MEM_WRITE_ONLY,
122         sizeof(int) * num_block, 0, &err);
123 }
124
125 void Create_program()
126 {
127     const char * src0 = src;
128     program = clCreateProgramWithSource(context, LEN(&src0), &src0, NULL, NULL);
129     err = clBuildProgram(program, num_device, devices, NULL, NULL, NULL);
130     kernel = clCreateKernel(program, "redution", NULL);
131 }
132
133 void Set_arg()
134 {
135     err = clSetKernelArg(kernel, 0, sizeof(cl_mem), &buffer);
136     err = clSetKernelArg(kernel, 1, sizeof(cl_mem), &sum_buffer);
137     err = clSetKernelArg(kernel, 2, sizeof(int) * NUM_THREAD, NULL);
138 }
139
140 void Execution()
141 {
142     const size_t globalWorkSize[1] = { N };
143     const size_t localWorkSize[1] = { NUM_THREAD };
144     err = clEnqueueNDRangeKernel(cmdQueue, kernel, 1, NULL, globalWorkSize,
145         localWorkSize, 0, NULL, NULL);
146     clFinish(cmdQueue);
147 }
148
149 void CopyOutResult(int*out)
150 {
151     err = clEnqueueReadBuffer(cmdQueue, sum_buffer, CL_TRUE, 0,
152         sizeof(int) * num_block, out, 0, NULL, NULL);
153 }

HelloJni.cpp

在jni文件夹下面添加Application.mk,内容如下。

APP_ABI := armeabi-v7a

Application.mk

在jni文件夹下面添加Android.mk,内容如下。

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)
LOCAL_MODULE    := AndroidOpenCL
LOCAL_SRC_FILES := HelloJni.cpp
LOCAL_LDFLAGS += -llog  -lOpenCL
include $(BUILD_SHARED_LIBRARY)

Android.mk

在项目中添加assets文件夹,在此文件夹内新建step.cl文件,内容如下。

 1 __kernel void redution(
 2     __global int *data,
 3     __global int *output,
 4     __local int *data_local
 5     )
 6 {
 7     int gid = get_group_id(0);
 8     int tid = get_global_id(0);
 9     int size = get_local_size(0);
10     int id = get_local_id(0);
11     data_local[id] = data[tid];
12     barrier(CLK_LOCAL_MEM_FENCE);
13     for (int i = size / 2; i>0; i >>= 1)
14     {
15         if (id<i)
16         {
17             data_local[id] += data_local[id + i];
18         }
19         barrier(CLK_LOCAL_MEM_FENCE);
20     }
21     if (id == 0)
22     {
23         output[gid] = data_local[0];
24     }
25 }

step.cl

最终解决方案资源管理器里看起来是这个样子的(显示所有文件状态)。

这样就可以重新生成再运行了。需要调试的话,直接在cpp文件中打断点就行了,很方便。

3.资源下载

整个工程的打包文件,其中包含了CL文件夹和libOpenCL.so文件,注意,这里的libOpenCL.so文件是从Nexus 7 2013 WiFi版中提取的,可能不适合你的设备。

链接: http://pan.baidu.com/s/1sjl04JN 密码: 6xtt

4.参考资料

[1]wcj0626,高通平台下安卓opencl小例子,2014.05.19,http://blog.csdn.net/wcj0626/article/details/26272019

[2]Vadim Kartoshkin (Intel),基于 Android* 操作系统的 OpenCL™ 入门,2014.05.12,https://software.intel.com/zh-cn/android/articles/opencl-basic-sample-for-android-os?utm_campaign=eoe&utm_source=eoe.cn&utm_medium=Link&utm_content=intel-optimization

PS:

第一次写技术blog,各位见谅,如有问题,欢迎讨论~

时间: 2024-10-15 06:24:41

使用NVIDIA Nsight Tegra建立OpenCL项目的相关文章

使用开源中国git建立私有项目

一.为什么使用oschina而不使用github呢? 原因是: 1.oschina服务器在国内,速度更快,而github在国外,国内网络不FQ访问速度受限: 2.oschina免费账户同样可以建立私有项目,而 GitHUB 上要建立私有项目必须付费. 二.使用oschina建立私有项目步骤: 1.首先去oschina上申请一个账号(貌似是句废话~): 2.添加 SSH 公钥,打开mac终端,输入 cd ~/.ssh 进入.ssh目录,输入 ls 查看当前目录下的文件: 3.生成 RSA 密钥对,

Axure如何如何建立共享项目、如何编辑共享项目、如何获取共享项目

如果小伙伴是一名编程工作者,我们不可以避免的会和Axure这块软件握手,但是但一个项目需要协同操作的时候,就需要用到项目共享的功能.类似我们的svn,想起机房合作的时候,每天早上来到427的我们,打开电脑,开始新的一天的工作,首先,我们从服务器下载项目组最新代码:其次,进入自己的分支,进行工作,每隔一个小时向服务器自己的分支提交一次代码(很多人都有这个习惯.因为有时候自己对代码改来改去,最后又想还原到前一个小时的版本,或者看看前一个小时自己修改了哪些代码,就需要这样做了).最后,当十点半的钟声在

eclipse下建立 android 项目,相关文件夹介绍

今天开始进入ANDROID开发,之前一直做些JAVA的WEBSERVICE之类的文件,第一次从头开始整理ANDROID项目,我会把最近遇到的问题做一一梳理. 现在来说一下建立ANDROID项目后产生的各个文件夹的作用.当我们建立一个基本的ANDROID环境时候,将自动出现如下文件夹. 1.src文件夹:2.gen文件夹:3.Android 2.1文件夹:4.assets:5.res文件夹:6.AndroidManifest.xml  1.SRC文件夹(存放源代码): 顾名思义(src, sour

[Servlet]Eclipse中建立web项目并使用servlet

1.建立web项目 前提是在Eclipse中配置好tomcat,Eclipse中配置tomcat请参考Eclipse中tomcat的配置 1)创建dynamic web project,只需要命名为web01_exec,其余默认设置即可: 2)next-next-勾选generate web.xml deployment description,该选项会在目录下生成一个默认的xml文件: 3)在java resource的src下建立命名为web的package,创建名为DateServlet的

mybatis 学习一 建立maven项目

一.直接建立Maven项目方法 1.建立Maven项目 接下来使用Eclipse的maven构建一个web项目,以构建SpringMVC项目为例: 1.1 选择建立Maven Project 选择File -> New -> Other,在New窗口中选择 Maven -> Maven Project.点击newxt. 1.2 选择项目路径 Use default Workspace location默认工作空间. 1.3 选择项目类型 在Artifact Id中选择maven-arch

建立spring项目入门实例

建立maven项目 打开pop.xml文件 添加springframework所依赖的包 <!-- https://mvnrepository.com/artifact/org.springframework/spring-context --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <

intellij idea建立maven项目

配置jdk 配置mvn http://jingyan.baidu.com/article/d8072ac45d3660ec94cefd51.html 右键"计算机",选择"属性",之后点击"高级系统设置",点击"环境变量",来设置环境变量,有以下系统变量需要配置: 新建系统变量   MAVEN_HOME  变量值:D:\Java\apache-maven-3.1.1 编辑系统变量  Path         添加变量值: ;%

pycharm无法新建django项目,报错timed out,需先建立pure项目,进入后建立django项目,最后调整目录层级。

一.pycharm无法新建django项目,报错timed out,需先建立pure项目,名字改成mysite: 二.进入后,在下方Terminal里,输入: pip install Django==2.2.7 用来安装指定版本的django 三.继续在下方Terminal里,输入: django-admin startproject mysite 创建一个名叫mysite的django项目. 四.执行后,你会发现目录结构有变化 点击右边的add configuration,然后点击弹出来窗口的

解决Eclipse建立Maven项目后无法建立src/main/java资源文件夹的办法

建立好一个Maven项目后,如果Java Resources资源文件下没有src/main/java文件夹,并且在手动创建这个文件时提示“已存在文件”. 这说明,在这个项目配置中已经有了src/main/java这个文件夹,至于为什么不显示,我暂时也还不清楚,希望谁明白了跟我下,谢了.(已解决) 第一种方法: 打开项目的classpath文件:如下 <?xml version="1.0" encoding="UTF-8"?><classpath&g