65.9K
CodeProject 正在变化。 阅读更多。
Home

开始在运行Android* OS的Intel®架构上使用RenderScript

2014 年 11 月 17 日

CPOL

6分钟阅读

viewsIcon

8842

RenderScript 是 Android 上的一种脚本语言。您可以使用它来编写高性能的图形渲染和原始计算代码。

引言

RenderScript 是 Android 上的一种脚本语言。您可以使用它来编写高性能的图形渲染和原始计算代码。

RenderScript API 包含用于 2D/3D 渲染和数学计算的高性能函数。它允许您描述一项任务,该任务涉及对大量数据进行类型相同、计算独立的计算,并将其分解为可以在运行 Android 的多核处理器平台上快速并行执行的相似子任务。

这项技术可以提高许多与图像处理、图像识别、物理模型等相关的 Dalvik 应用程序的性能,而这些应用程序本身是与机器无关的。

关于 Android 内的 RenderScript 技术

  1. RenderScript 离线编译

    RenderScript 最初出现在 Honeycomb / Android 3.0 (API 11) 中。在 Android SDK 目录的 platform-tools 中,您可以找到 llvm-rs-cc(离线编译器),用于将 RenderScript(*.rs 文件)编译成字节码(*.bc 文件),并为 RenderScript 内的结构、全局变量以及 RenderScript 本身生成 Java* 类对象(*.java 文件)。llvm-rs-cc 基于 Clang 编译器,并针对 Android 进行了少量修改,它是 LLVM 编译器 的前端。此图描述了离线编译的工作原理。

  2. RenderScript 运行时编译

    新的 Android 框架构建在 LLVM 后端之上,负责运行时编译字节码、与正确库链接以及启动和控制 RenderScript。该框架包含以下组件:libbcc 负责 LLVM 上下文初始化、解析字节码中的 pragmas 和其他元数据、字节码编译以及与 libRS 中所需库的动态链接。libRS 包含库(数学、时间、绘图、引用计数等)、结构和数据类型(Script、Type、Element、Allocation、Mesh、各种矩阵等)。下图显示了运行时编译。

RenderScript 的优势

  • 编译器生成与机器无关的应用程序,因为包含在 apk 文件中的 RenderScript 字节码将在运行时被编译成目标运行平台的 CPU 的本地代码。
  • 通过计算并行化、运行时编译器优化和本地代码执行,实现了高速执行。

缺点

  • RenderScript 详细文档的缺乏使得应用程序开发变得复杂。RenderScript 运行时 API 的有限运行时文档在此处 显示。但是,您可以在此处找到详细的“入门”教程 这里
  • 不支持在 GPU 或 DSP 上执行 RenderScript 线程。您可能会遇到在异构运行中运行时线程平衡以及使用共享内存的问题。

RenderScript 的示例用法:将 RGB 颜色转换为单色图像

RenderScript 基于 C 语言。如果您已经了解 C 语言,将能很快学会它。此外,使用它的原理与 OpenGL* 类似。

在 Intel 的工作中,我们经常使用 RenderScript 或 OpenGL 来加速 Dalvik 函数。

这是一个 Dalvik 函数 Dalvik_MonoChromeFilter 的示例,它负责将 RGB 彩色图像转换为单色图像。

private void DalvikFilter() {
    float MonoMult[] = {0.299f, 0.587f, 0.114f};
    int mInPixels[] = new int[mBitmapIn.getHeight() * mBitmapIn.getWidth()];
    int mOutPixels[] = new int[mBitmapOut.getHeight() * mBitmapOut.getWidth()];
    mBitmapIn.getPixels(mInPixels, 0, mBitmapIn.getWidth(), 0, 0,
            mBitmapIn.getWidth(), mBitmapIn.getHeight());
    for(int i = 0;i < mInPixels.length;i++) {
        float r = (float)(mInPixels[i] & 0xff);
        float g = (float)((mInPixels[i] >> 8) & 0xff);
        float b = (float)((mInPixels[i] >> 16) & 0xff);
 
        int mono = (int)(r * MonoMult[0] + g * MonoMult[1] + b * MonoMult[2]);
 
        mOutPixels[i] = mono + (mono << 8) + (mono << 16) + (mInPixels[i] & 0xff000000);
        }
    mBitmapOut.setPixels(mOutPixels, 0, mBitmapOut.getWidth(), 0, 0,
            mBitmapOut.getWidth(), mBitmapOut.getHeight());
}

正如您所见,代码中有一个简单的循环,其迭代是独立的,处理像素流。

在实验中,我们在配备 Intel® Atom™ 处理器和 600x1024 分辨率图片的 Lenovo K900 手机上运行了代码,图片内容是一个携带圣诞礼物的 LEGO* 怪物。

这是一个 RS_MonoChromeFilter 函数的示例(RenderScript 实现来自 Android SDK,根据 Apache 2.0 许可证 获得授权),用于将 RGB 彩色图像转换为单色图像。

private RenderScript mRS;
private Allocation mInAllocation;
private Allocation mOutAllocation;
private ScriptC_mono mScript;
…
private void RS_MonoChromeFilter() {
mRS = RenderScript.create(this);//RenderScript context creating
mInAllocation = Allocation.createFromBitmap(mRS, mBitmapIn,
            Allocation.MipmapControl.MIPMAP_NONE,
                Allocation.USAGE_SCRIPT);/*allocation and initialization of shared memory */
        mOutAllocation = Allocation.createTyped(mRS,
mInAllocation.getType());
        mScript = new ScriptC_mono(mRS, getResources(), R.raw.mono); /*creating and binding RenderScript to the context */      
        mScript.forEach_root(mInAllocation, mOutAllocation);/*Call root function by two SMP threads */
         
        mOutAllocation.copyTo(mBitmapOut);
}
 
//mono.rs
//or our small RenderScript
#pragma version(1)
#pragma rs java_package_name(com.example.hellocompute)
 
//multipliers to convert a RGB colors to black and white
const static float3 gMonoMult = {0.299f, 0.587f, 0.114f};
 
void root(const uchar4 *v_in, uchar4 *v_out) {
  //unpack a color to a float4
  float4 f4 = rsUnpackColor8888(*v_in);
  //take the dot product of the color and the multiplier
  float3 mono = dot(f4.rgb, gMonoMult);
  //repack the float to a color
  *v_out = rsPackColorTo8888(mono);
}

RenderScript 优化示例

通过对浮点运算使用更激进的优化,可以提高 RenderScript 的性能。在下面的代码片段中,我们在 RenderScript 中添加了 rs_fp_imprecise pragma,以在不损失任何图像质量的情况下加快计算速度。

//mono.rs
//or our small RenderScript
#pragma version(1)
#pragma rs java_package_name(com.example.hellocompute)
#pragma rs_fp_imprecise
//multipliers to convert a RGB colors to black and white
const static float3 gMonoMult = {0.299f, 0.587f, 0.114f};
 
void root(const uchar4 *v_in, uchar4 *v_out) {
  //unpack a color to a float4
  float4 f4 = rsUnpackColor8888(*v_in);
  //take the dot product of the color and the multiplier
  float3 mono = dot(f4.rgb, gMonoMult);
  //repack the float to a color
  *v_out = rsPackColorTo8888(mono);
}

优化后的代码产生相同质量的单色图像,没有伪影和失真。与 NDK 不同,RenderScript 没有显式控制运行时编译器优化的机制,因为编译器标志先前是在 Android 中为每个平台(x86、ARM 等)声明的。

关于作者

Stanislav Pavlov 在英特尔公司软件与服务集团工作。他拥有 10 多年的软件开发经验。他的主要兴趣是优化性能、功耗和并行编程。作为一名为基于 Intel® 的设备提供技术支持的应用工程师,Stanislav 与软件开发人员和 SoC 架构师密切合作,帮助他们在 Intel 平台上实现最佳性能。Stanislav 拥有俄罗斯国立高等经济大学数学经济学硕士学位。他目前正在莫斯科商学院攻读 MBA。

本文的合著者 Roman Kazantsev 也是软件与服务集团的高级软件工程师,专注于加密项目。他拥有俄罗斯下诺夫哥罗德国立大学计算机科学硕士学位,目前正在该校攻读博士学位。

注意事项
本文档中的信息是为配合 Intel 产品提供的。本文档不授予任何明示或暗示的、禁止反言的或以其他方式授予的知识产权许可。除 Intel 产品销售条款和条件另有规定外,Intel 对本文档概不承担任何责任,并否认与 Intel 产品销售和/或使用相关的任何明示或暗示的保证,包括对特定用途的适用性、适销性或对任何专利、版权或其他知识产权的侵权保证。

除非 Intel 书面同意,否则 Intel 产品不设计也不用于任何可能导致人员伤亡的应用程序。

Intel 可随时更改规格和产品说明,恕不另行通知。设计人员不得依赖任何标记为“保留”或“未定义”的特性或指令的缺失或特征。Intel 为将来的定义保留这些内容,并且对因其未来更改而引起的任何冲突或不兼容性概不负责。此处提供的信息可能会发生变更,恕不另行通知。请勿基于此信息最终确定设计。

本文档中描述的产品可能包含已知为勘误的设计缺陷或错误,这可能导致产品偏离已发布的规范。当前的已表征勘误可应要求提供。

请联系您当地的英特尔销售办事处或您的经销商以获取最新的规范,并在下订单前进行咨询。

订购号与本文档中引用的文档副本,或其他 Intel 文献,可通过致电 1-800-548-4725 获取,或访问:http://www.intel.com/design/literature.htm

性能测试中使用的软件和工作负载可能仅针对 Intel 微处理器进行了性能优化。性能测试(如 SYSmark* 和 MobileMark*)是通过使用特定的计算机系统、组件、软件、操作和功能来衡量的。对任何这些因素的任何更改都可能导致结果有所不同。您应查阅其他信息和性能测试,以帮助您全面评估您打算购买的产品,包括该产品与其他产品结合使用时的性能。

本文档中重印的任何软件源代码均根据软件许可证提供,并且只能根据该许可证的条款使用或复制。

Intel、Intel 徽标和 Atom 是 Intel Corporation 在美国和/或其他国家的商标。

版权所有 © 2014 英特尔公司。保留所有权利。

*其他名称和品牌可能被声明为他人的财产。

© . All rights reserved.