📜 ⬆️ ⬇️

Android: Writing Multi-threaded Applications with Intel® Threading Building Blocks

Most recently, we considered writing multi-threaded applications for a Windows store using Intel Threading Building Blocks ( Intel TBB ). It argues that using the cross-platform TBB library makes it easy to transfer the computing part to other platforms. Android just fit for a good example of one of the "other platforms", details under the cat.

In the recently released release of the Intel TBB library tbb41_20121112oss, which is available for download on our website threadingbuildingblocks.org , experimental support for Android applications has been added, i.e. building native libraries for using Android applications through the JNI interface.

To build the library, we will use the Android SDK Tools Rev.21 and Android NDK Rev 8C. But here it is necessary to make a reservation, which, as it turned out when preparing the material, was affected by experimentation and the construction of the libraries themselves in this release. Out of the Box only works under NDK on Linux. We will fix this in one of the following updates. I filed a little makefile for Windows and built a library there, but for simplicity, we will assume that the library itself was built on Linux, and everything else was done on Windows. In general, there is another advantage of the cross-platform library.

So, what needs to be done to build a simple application using Intel TBB.
First you need to unpack and compile the library, since this release is distributed only in source code. It is implied that there is gnu make, on the command line with the NDK environment set, we execute the command
')
gmake tbb tbbmalloc target=android 

From the library side, go to Eclipse. Using templates, we create a simple application and, for simplicity, as in the previous case, let's call it app1:


Activity choose FullscreenActivity. This completes the template work. Please note that com.example * apps are not welcome by the Google Store. But for example, it will do.

Then add a couple of buttons to the main frame. After that, the XML file of the main frame (app1 / res / layout / activity_fullscreen.xml) will look something like this

 <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> 

And the file with strings (app1 / res / values ​​/ strings.xml) will look like this:
 <?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> 

Also add button handlers
 // 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); } 

And loading libraries in FullscreenActivity.java
  @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); … System.loadLibrary("tbb"); System.loadLibrary("jni-engine"); } 

If everything should be clear with the “tbb” library, then you need to dwell on the “jni-engine”.

The “jni-engine” is a C ++ library that implements the computational part and exposes the C-interfaces for the JNI calls to onClickSRCall () and onClickDRCall ().

According to the rules of development within the project, we create the directory “jni” and create there 3 files specific to our “jni-engine” library. It:
Android.mk (in <> brackets data in which you need to substitute actual values)
 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 := system 

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(); } 

As you can see, we use the same algorithms as in the previous blog.

When building with NDK, he decomposes the libraries into the necessary directories, including libjni-engine.so and libtbb.so.

Now go back to eclipse and build the .apk file. The application is ready for installation on AVD or on the device. This is what AVD looks like:



That's all! Our simple application is written! And for those who used the code of the previous blog, the application was successfully transferred to Android.

For those interested, try:

Download Intel Threading Building Blocks Library (Open Source Version):
threadingbuildingblocks.org
Commercial version of Intel TBB (not functionally different):
software.intel.com/en-us/intel-tbb

English and Russian blogs about Intel TBB
software.intel.com/en-us/tags/17207
software.intel.com/en-us/tags/17220
And, of course, our forum,
software.intel.com/en-us/forums/intel-threading-building-blocks

Source: https://habr.com/ru/post/161527/


All Articles