第1章 RenderScript

RenderScript提供一个独立于平台并在本地运行的计算引擎,用它来加速你需要大量计算能力的应用。RenderScript是一个运行与Android上计算密集型的高性能架构。RenderScript主要是面向数据的并行计算,虽然串行计算密集型负载也不错。RenderScript运行时将在所有可用的处理器上并行工作,如多核CPU,GPU或DSP,让你专注于算法而不是调度工作或负载均衡。RenderScript对于图像处理,计算摄影或计算机视觉这样的应用程序尤其有用。对于RenderScript,你先要明白两个概念:

1.高性能计算内核由C99语言编写

2.Java API用于管理RenderScript的资源寿命和控制核心的执行

1.1 写一个RenderScript内核

一个RenderScript内核通常驻留在一个.rs文件中,它在<project_root>/src/目录下,每一个rs文件被叫做一个脚本。每个脚本包含它自己的一套内核,函数和变量。一个脚本可以包含:

◆编译指示声明(#pragma version(1))用来声明一个RenderScript内核语言的版本。目前,1是唯一的有效值

◆编译指示声明(#pragma rs java_package_name(com.example.app))用来声明一个Java类的包名

◆一些调用函数。一个调用函数是一个单线程RenderScript函数,你能从你的java代码中使用任意参数来调用。这些经常用于初始化设置或在一个巨大的处理管道内进行串行计算。

◆一些脚本的全局变量,一个脚本的全局变量等价于一个在C中的全局变量。你能从java代码中访问脚本全局变量,并且这些变量经常被用于参数传递到RenderScript内核中。

◆一些计算内核,一个内核是一个并行函数,执行配置中的每一个元素。

下面是一个简单的例子:如代码清单1-1所示:

uchar4 __attribute__((kernel)) invert(uchar4 in, uint32_t x, uint32_t y) {

  uchar4 out = in;

  out.r = 255 - in.r;

  out.g = 255 - in.g;

  out.b = 255 - in.b;

  return out;

}

代码清单1-1

在许多方面,这是一个标准的C函数。第一个显著的特点是__attribute__((kernel))应用函数原型。这是指此函数是一个RenderScript内核而不是调用函数。接下来的特性是在参数及其类型。在RenderScript内核,这是一个特殊的参数,它自动填充基于输入配置传递给内核启动。默认情况下,内核跨整个配置运行,在配置中每个元素都带一个内核执行体。第三个显著的特性是内核的返回类型。在输出配置中,返回的值从内核自动写入到适当的位置。RenderScript运行时检查以确保输入和输出元素配置匹配内核原型,如果它们不匹配,则抛出一个异常。

一个内核可以有一个输入配置或一个输出配置,或两者都有。一个内核可能没有一个以上的输入或输出配置。如果一个以上的输入和输入是必须的,那些对象将结合rs_allocation 脚本全局变量并通过rsGetElementAt_type()或rsSetElementAt_type()从一个内核或者调用函数访问。一个内核可以使用X,Y,Z参数访问当前执行的坐标。这些参数是可选的,但坐标的参数类型必须是uint32_t

一个可选的init()函数。一个init()函数是一种特殊类型的调用函数,当脚本首次实例化时,需要调用它。这使得一些计算自动发生在脚本创建时。

一些静态脚本全局变量和函数。静态脚本全局变量几乎等价于脚本全局变量,只是静态不允许从java代码调用。静态函数是一个标准的C函数,它能被任意内核或调用函数调用,而不用暴露在Java API。如果一个脚本全局变量或函数不需要从java代码中调用,那么强烈建议声明为静态的。

设置浮点精度

你可以在一个脚本中控制所需的浮点精度,如果完整的IEEE 754-2008标准是有用的。那么以下编译指示可以设置一个不同的浮点精度等级:

◆#pragma rs_fp_full (默认如果没有什么被指定): 应用程序需要通过IEEE754-2008标准的浮点精度概述。

◆#pragma rs_fp_relaxed应用程序不需要严格的IEEE 754-2008标准并可以允许不精确,对于de-norms计算这种模式启动了清零(flush-to-zero),并且向零舍入(round-towards-zero)。

◆#pragma rs_fp_imprecise 应用程序不具有严格的精度要求。这种模式可以使一切rs_fp_relaxed 按照以下操作:

操作导致-0.0被+0.0代替返回

操作在INF和NAN在未定义。

大多数应用程序可以使用relaxed无任何副作用。这对于一些只提供relaxed精度的架构并需要额外优化的情况来说,这是非常有益的。(如SIMD CPU指令)

1.2 访问RenderScript API

当开发使用RenderScript开发Android应用程序时,你能通过以下其中一种方式来访问API:

◆android.renderscript这个API在Android3.0以上是可用的,这些对于RenderScript都是原始API并且当前没有更新。

◆android.support.v8.renderscript这个API需要通过Support Library才可用,这样允许你在Android2.2或更高版本中使用他们

官方强烈推荐使用Support Library API来访问RenderScript。因为它们包含计算框架最新的改进以及支持更广泛的设备兼容性。下面我们来使用RenderScript Support Library APIs

为了使用这个API,必须配置我们的开发环境。首选需要Android SDK Tool为22.2或更高。Android SDK Build 为18.1.0或更高。你能通过Android SDK Manager来更新安装版本。注意RSSL(RenderScript Support Library)API目前不支持Android Studio或Gradle编译。下面我们将在Eclipse中使用RSSL:

1.确保你有必要的Android SDK版本和编译工具版本

2.打开项目中的project.properties文件

3.添加以下几行到文件中

renderscript.target=18

renderscript.support.mode=true

sdk.buildtools=18.1.0

4.在你的类中使用RenderScript,导入Support Library:

import android.support.v8.renderscript.*;

project.properties设置了以上几行来控制Android在编译时的行为:

◆renderscript.target指定生成的字节码版本。官方推荐你设置这个值为可用的最高值并且设置renderscript.support.mode为true。从11到最新的API LEVEL在这之间设置任意整形值都是合法的。如果你的最小SDK版本在manifest中指定的值也为当前的SDK版本的较高值,那么renderscript.target将被忽略并且将目标值设置为最小SDK版本。

◆renderscript.support.mode如果它在不支持目标版本的设备上运行时,指定生成的字节码回滚兼容版本

◆sdk.buildtools指Android SDK编译工具使用的版本。这个值被设置为18.1.0或更高,如果你不指定这个值,会使用你当前最高安装的编译工具版本。你应该设置这个值,确保在不同的开发机器上保持一致性

1.3 在Java代码中使用RenderScript

在Java代码中使用RS需要依赖android.renderscript或android.support.v8.renderscript包。大多数应用程序遵循基本的使用模式

1.初始化一个RenderScript的context。这个RenderScript context在create(Context)中被创建,确保RenderScript能被使用并且提供一个对象来控制后来的RenderScript对象的生命周期。你应该考虑context创建与一个潜在的长时间运行的操作,因为它可能在不同的硬件块创建资源,如果可能的话,它不应该在应用程序的关键路径。通常,一个应用程序在一个时间内只有一个单一的RenderScript context。

2.通过一个叫脚本创建至少一个Allocation。一个Allocation是一个RenderScript对象,它提供一个固定的数据量存储。在脚本中的内核带来Allocation对象作为它们的输入输出,当作为脚本全局变量绑定时,并且Allocation对象在内核中能被rsGetElementAt_type()和 rsSetElementAt_type()访问。Allocation对象允许从java代码到RenderScript代码传递数组,相反的方向也可以。Allocation对象通常使用createTyped(RenderScript, Type)或createFromBitmap(RenderScript, Bitmap)来创建。

3.创建任意脚本是必要的。在使用RenderScript时,有2种脚本类型可用:

ScriptC:这些都是用户定义的脚本描述在上面(1.1写一个RenderScript内核)小节中。每个脚本有一个Java类反射,通过RenderScript编译器可以很容易的从java代码中访问脚本;这个类命名被ScriptC_filename。例如如果内核位于invert.rs中并且RenderScript context已经位于mRS中,java代码实例化脚本的方法如下:

ScriptC_invert invert = new ScriptC_invert(mRenderScript);

ScriptIntrinsic:这些是常见的操作:如高斯模糊,回旋,图像融合。更多信息,请参考ScriptIntrinsic的子类。

4.数据填充Allocation。除了用android.renderscript创建Allocation,在首次创建时一个Allocation也能被空数据填充。为了填充一个Allocation,在Allocation里使用一个copy方法。

5. 设置必要的脚本全局变量。全局变量命令规则最好使用set_globalname。例如,为了设置一个int类型的elements名字变来那个,使用java方法set_elements(int)。RenderScript对象在内核中也能被设置,例如,rs_allocation变量命名为lookup,能被方法set_lookup(allocation)设置。

6.启动适当的内核。方法来启动一个给定的内核将被反射到同样的ScriptC_filename类使用名为forEach_kernelanme()的方法。这些启动器是异步的,并且启动将按照他们的启动顺序被序列化。依赖你内核参数,这个方法将带来一个或者两个Allcation。默认情况下,一个内核将执行整个输入或输出Allcation;通过适当的Script.LaunchOptions作为最后一个参数到forEach方法来执行完一个Allcation的子集。调用函数能使用invoke_functionname方法来启动,在同样的ScriptrC_filename类中被反射。

7.出于Allocation对象复制数据。为了使用java代码从Allocation中访问数据,数据必须在Allocation中使用一个copy方法复制到java缓冲区, 这些函数将和异步内核一起同步并作为必要的函数启。

8.拆除RenderScript context。RenderScript context能通过destroy()方法或通过垃圾回收来摧毁。这将导致后面使用任意附属到context的对象抛出一个异常。

第三部分:Android 应用程序接口指南---第五节:计算---第一章 RenderScript的更多相关文章

  1. 第三部分:Android 应用程序接口指南---第四节:动画和图形---第一章 属性动画及动画与图形概述

    第1章 属性动画及动画与图形概述 Android提供了一系列强大的API来把动画加到UI元素中,以及绘制自定义的2D和3D图像中去.下面的几节将综述这些可用的API以及系统的功能,同时帮你做出最优的选 ...

  2. 第三部分:Android 应用程序接口指南---第二节:UI---第四章 Action Bar

    第4章 Action Bar Action Bar是一个能用于确定应用程序和用户的位置,并提供给用户操作和导航模式的窗口功能.如果需要显著地展示当前用户的操作或导航,应该使用Action Bar,因为 ...

  3. 第三部分:Android 应用程序接口指南---第一节:应用程序组件---第一章1-1.Fragment

    第1-1章 Fragments 在Activity中的fragment代表的是一种行为或用户界面的一部分.你可以在activity中结合多个fragments创建一个多面板UI,并可以在多个activ ...

  4. 第三部分:Android 应用程序接口指南---第二节:UI---第一章 用户界面和布局

    第1章 用户界面和布局 应用程序的用户界面就是用户能看到并可以与它交互的任何东西.Android提供多种预置的UI组件,如结构化布局对象和允许你为应用程序创建图形用户界面的UI控件.Android也会 ...

  5. 第三部分:Android 应用程序接口指南---第二节:UI---第二章 输入控件

    第2章 输入控件 输入控件是应用程序中用户接口的一种交互式组件.Android提供了大量的可供人们在UI中使用的控件,比如按钮.文本区域.(带滑块的)进度条.复选框.缩放按钮以及切换按钮等等. 在UI ...

  6. 第三部分:Android 应用程序接口指南---第二节:UI---第三章 菜单

    第3章 菜单 在许多不同类型的应用中,菜单通常是一种用户界面组件.为了提供给用户提供熟悉且一致的体验,你需要使用菜单API来展示用户动作和你Activity中的其他选项. 从安卓3.0系统(API l ...

  7. 第三部分:Android 应用程序接口指南---第二节:UI---第五章 设置(Settings)

    第5章 设置(Settings) 应用程序通常包括允许用户修改应用程序的特性和行为的设置功能.例如,一些应用程序允许用户指定通知是否启用或指定多久使用云同步数据.如果你想要为你的应用程序提供设置,你应 ...

  8. 第三部分:Android 应用程序接口指南---第二节:UI---第六章 对话框

    第6章 对话框 一个对话框是一个小窗口,提示用户做出决定或输入额外的信息,一个对话框不填充屏幕并且通常用于在程序运行时中断,然后弹出通知提示用户,从而直接影响到正在运行的程序.图6-1就是对话框的外观 ...

  9. 第三部分:Android 应用程序接口指南---第二节:UI---第八章 Toast通知

    第8章 Toast通知 Toast通知是在窗口前面弹出的信息.它只占有信息所需要的空间量,并且用户当前的activity仍然是可见的.可互动的.这种通知自动地淡入和淡出,它不接受交互事件.他相当于一种 ...

随机推荐

  1. 【noip模拟赛8】魔术棋子

    描述 在一个M*N的魔术棋盘中,每个格子中均有一个整数,当棋子走进这个格子中,则此棋子上的数会被乘以此格子中的数.一个棋子从左上角走到右下角,只能向右或向下行动,请问此棋子走到右下角后,模(mod)K ...

  2. 6.Django与Ajax

    Ajax 文件夹为Ajaxdemo 向服务器发送请求的途径: 1.浏览器地址栏,默认get请求: 2.form表单: get请求 post请求 3.a标签,超链接(get请求) 4.Ajax请求 特点 ...

  3. C#介绍

    1.c#与.net框架 c#属于.net框架的一个子集. 2..net框架 3.BCL 基类库 4.编译过程 5.运行过程 6.总结 7.CLR

  4. linux shell cut 命令

    cut命令 cut命令用于从文件或者标准输入中读取内容并截取每一行的特定部分并送到标准输出. 截取的方式有三种:一是按照字符位置,二是按照字节位置,三是使用一个分隔符将一行分割成多个field,并提取 ...

  5. 高效遍历匹配Json数据与双层for循环遍历Json数据

    工作中往往遇到这种情况,保留用户操作痕迹,比如用户选择过得东西,用户进入其它页面再返回来用户选择的的数据还在. 比如:1.购物车列表中勾选某些,点击任意一项,前往详情页,再返回购物车依旧需要呈现勾选状 ...

  6. PHP如何支持CURL字符串证书传输

    背景 最近在对接微信支付的时候,需要在退款处用到证书,由于我们是SAAS平台,要支持多方多渠道支付,如果把所有证书文件保存在应用服务器会受到SLB的影响,会导致某台机器文件不同步而阻碍退款流程,但把文 ...

  7. Redis实现的分布式锁和分布式限流

    随着现在分布式越来越普遍,分布式锁也十分常用,我的上一篇文章解释了使用zookeeper实现分布式锁(传送门),本次咱们说一下如何用Redis实现分布式锁和分布限流. Redis有个事务锁,就是如下的 ...

  8. maven 多个jar包版本依赖问题

    maven 中使用jar包的多个版本容易造成依赖问题,解决问题的方式可以将 使用jar包的版本排除掉,比如dubbo使用netty 4.0.33版本可以将dubbo排除掉 netty依赖,这样其他ja ...

  9. loj#2054. 「TJOI / HEOI2016」树

    题目链接 loj#2054. 「TJOI / HEOI2016」树 题解 每次标记覆盖整棵字数,子树维护对于标记深度取max dfs序+线段树维护一下 代码 #include<cstdio> ...

  10. 通过Queue方法实现进程间通信

    from multiprocessing import Process,Queue import time def write(q): ): q.put(i) # time.sleep() print ...