Android* 教程: 使用 Intel® Threading Building Blocks 开发多线程应用程序





5.00/5 (1投票)
在最近发布的 Intel Threading Building Blocks (Intel® TBB) 稳定版本中,我们增加了对 Android 应用程序的实验性支持;即,构建 Intel TBB 库,以便通过 JNI 接口在 Android 应用程序中使用。
引言
最近,我们发布了“Windows* 8 教程:使用 Intel® Threading Building Blocks 为 Windows 应用商店* 编写多线程应用程序”。我们在那里指出,并行计算引擎可以轻松移植到其他移动或桌面平台。 Android 就是这样一个移动平台的一个很好的例子。
在最近发布的 Intel Threading Building Blocks (Intel® TBB) 稳定版本中,我们增加了对 Android 应用程序的实验性支持;即,构建 Intel TBB 库,以便通过 JNI 接口在 Android 应用程序中使用。您可以从 threadingbuildingblocks.org 下载此版本。
要在 Linux* 主机上启动此过程,请解压 Intel TBB 源代码发行版,获取 <unpacked_dir>/build/android_setup.csh 脚本的源代码,并构建库。构建库是必要的,因为开发版本仅以源代码形式分发。 <unpacked_dir>/build/index.android.html 文件包含在 Linux 上配置环境和构建库的说明。
假设 gnu make 3.81 在 %PATH% (在 Microsoft Windows* 主机平台上) 和 $PATH (在 Linux 主机上) 中可用,我们需要在 NDK 环境中发出以下命令来构建用于 Android 的 Intel TBB 库
gmake tbb tbbmalloc target=android
这就是库构建所需的一切;我们现在可以移动到使用 Eclipse* 构建示例。对于下面的示例,我将在 Windows* 上使用 Android SDK Tools Rev.21 和 Android NDK Rev 8C 来演示跨平台开发的流程。
使用默认模板 «New Android Application» 创建一个新项目。为简单起见,我们将其命名为 "app1",与之前的帖子相同
选择 FullscreenActivity
作为 Activity。这就是模板的全部内容。请注意,com.example* 不是 Google Play* 可接受的包命名,但对于我们的示例来说已经足够了。
然后将几个按钮添加到主框架。添加这些后,主框架的 XML 文件 (app1/res/layout/activity_fullscreen.xml) 将如下所示
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#0099cc"
tools:context=".FullscreenActivity" >
<TextView
android:id="@+id/fullscreen_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:keepScreenOn="true"
android:text="@string/dummy_content"
android:textColor="#33b5e5"
android:textSize="50sp"
android:textStyle="bold" />
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true" >
<LinearLayout
android:id="@+id/fullscreen_content_controls"
style="?buttonBarStyle"
android:layout_width="match_parent"
android:layout_height="74dp"
android:layout_gravity="bottom|center_horizontal"
android:background="@color/black_overlay"
android:orientation="horizontal"
tools:ignore="UselessParent" >
<Button
android:id="@+id/dummy_button1"
style="?buttonBarButtonStyle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/dummy_button1"
android:onClick="onClickSR" />
<Button
android:id="@+id/dummy_button2"
style="?buttonBarButtonStyle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/dummy_button2"
android:onClick="onClickDR" />
</LinearLayout>
</FrameLayout>
</FrameLayout>
字符串文件 (app1/res/values/strings.xml) 将如下所示
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">Sample</string>
<string name="dummy_content">Reduce sample</string>
<string name="dummy_button1">Simple Reduce</string>
<string name="dummy_button2">Deterministic Reduce</string>
</resources>
然后添加按钮处理程序
// JNI functions private native float onClickDRCall(); private native float onClickSRCall(); public void onClickDR(View myView) { TextView tv=(TextView)(this.findViewById(R.id.fullscreen_content)); float res=onClickDRCall(); tv.setText("Result DR is n" + res); } public void onClickSR(View myView) { TextView tv=(TextView)(this.findViewById(R.id.fullscreen_content)); float res=onClickSRCall(); tv.setText("Result SR is n" + res); }
并将库加载到 FullscreenActivity.java 文件
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); … System.loadLibrary("gnustl_shared"); System.loadLibrary("tbb"); System.loadLibrary("jni-engine"); }
对于 "tbb" 库,一切都应该很清楚,并且需要 "gnustl_shared" 库来支持 TBB 的 C++ 语言特性。但是,对于 "jni-engine" 库,我们需要进行更详细的说明。
"jni-engine" 是一个 С++ 库,它实现了一个计算引擎并为名为 onClickSRCall()
和 onClickSRCall()
的 JNI 调用导出 C 接口。
根据 NDK 开发规则,在工作区内创建文件夹 "jni",并在其中创建 3 个特定于我们的 "jni-engine" 库的文件。
这些文件是
Android.mk
(<> 括号中的文本应该替换为实际值)
LOCAL_PATH := $(call my-dir)
TBB_PATH := <path_to_the_package>
include $(CLEAR_VARS)
LOCAL_MODULE := jni-engine
LOCAL_SRC_FILES := jni-engine.cpp
LOCAL_CFLAGS += -DTBB_USE_GCC_BUILTINS -std=c++11 -I$(TBB_PATH)/include
LOCAL_LDLIBS := -ltbb -L./ -L$(TBB_PATH)/<path_to_libtbb_so>
include $(BUILD_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := libtbb
LOCAL_SRC_FILES := libtbb.so
include $(PREBUILT_SHARED_LIBRARY)
Application.mk
APP_ABI := x86
APP_GNUSTL_FORCE_CPP_FEATURES := exceptions rtti
APP_STL := gnustl_shared
jni-engine.cpp
#include <jni.h>
#include "tbb/parallel_reduce.h"
#include "tbb/blocked_range.h"
float SR_Click()
{
int N=10000000;
float fr = 1.0f/(float)N;
float sum = tbb::parallel_reduce(
tbb::blocked_range<int>(0,N), 0.0f,
[=](const tbb::blocked_range<int>& r, float sum)->float
{
for( int i=r.begin(); i!=r.end(); ++i )
sum += fr;
return sum;
},
[]( float x, float y )->float
{
return x+y;
}
);
return sum;
}
float DR_Click()
{
int N=10000000;
float fr = 1.0f/(float)N;
float sum = tbb::parallel_deterministic_reduce(
tbb::blocked_range<int>(0,N), 0.0f,
[=](const tbb::blocked_range<int>& r, float sum)->float
{
for( int i=r.begin(); i!=r.end(); ++i )
sum += fr;
return sum;
},
[]( float x, float y )->float
{
return x+y;
}
);
return sum;
}
extern "C" JNIEXPORT jfloat JNICALL Java_com_example_app1_FullscreenActivity_onClickDRCall(JNIEnv *env, jobject obj)
{
return DR_Click();
}
extern "C" JNIEXPORT jfloat JNICALL Java_com_example_app1_FullscreenActivity_onClickSRCall(JNIEnv *env, jobject obj)
{
return SR_Click();
}
我们使用与之前博客中使用的相同算法。
当我们使用 NDK 构建时,它会将库编译到所需的文件夹,包括我们的库 libjni-engine.so、libgnustl_shared.so 和 libtbb.so。
接下来,切换回 Eclipse 并构建 app1.apk 文件。现在应用程序已准备好安装在 AVD 或实际硬件上。在 AVD 上它看起来像
就这样!这个简单的应用程序已经准备就绪,应该是一个很好的起点,可以编写更复杂的 Android 并行应用程序。对于那些使用来自 之前博客 的代码的人来说,该应用程序已成功移植到 Android。
* 其他名称和品牌可能被声明为他人财产。
相关文章与资源
要了解更多关于安卓开发者的英特尔工具,请访问英特尔® 安卓开发者专区。