Intel® Developer Zone offers tools and how-to information for cross-platform app development, platform and technology information, code samples, and peer expertise to help developers innovate and succeed. Join our communities for Android, Internet of Things, Intel® RealSense™ Technology, and Windows to download tools, access dev kits, share ideas with like-minded developers, and participate in hackathon’s, contests, roadshows, and local events.
Many Android* devices have processors with more than one core and knowing how to develop multithreaded applications has become important in the mobile industry. Intel has developed a valuable tool for developing parallel applications called Intel® Threading Building Blocks (Intel® TBB). The Intel® TBB is a cross-platform library of templates for creating parallel programs. It creates and synchronizes streams of data, hiding the details of the architecture and allowing you to work at a higher level of abstraction. Intel® TBB works on all architectures. For Android, use version 4.3 and above.
Build Intel® TBB
- Download TBB. You can download Intel® TBB here: https://www.threadingbuildingblocks.org/. I downloaded the sources of the last stable release (4.3 Update 1).
- Add NDK to PATH:
For Windows*:
For Linux*:
- Unzip TBB and go to the directory with source code and in src folder.
$ cd /src/
- Run TBB for Android:
$ /ndk-build –C /src/ arch=intel64 compiler=gcc target=android clean tbb tbbmalloc –j
This command builds TBB for Android 64 bit. For building TBB for Android 32 bit, change arch=intel64 on arch=ia32
. It will build the application for Android 64 bit architecture. - The library is built. In build directory (/build/) you can find directories with libs:
libgnustl_shared.so, libtbbmalloc_proxy.so, libtbbmalloc.so and libtbb.so. libtbb.so and libgnustl_shared
. so we will use in our application.
Calculate π
To calculate π you can choose any formula with a definite integral from Wikipedia: https://en.wikipedia.org/wiki/List_of_formulae_involving_%CF%80#Integrals. I chose this formula:
For this program I modified the formula:For this program I modified the formula: For this program I modified the formula:
For integral calculating I used the rectangle method. The integrated function is divided into N = 107 equal subintervals of length h = 2·10-7. The approximation to the integral is then calculated by adding up the areas (base multiplied by height) of the N rectangles, giving the formula:
Create Application
To create a new Android application:
Create Main Activity
In the res/layout/activity_main.xml
paste the following code:
<RelativeLayout 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:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="intel.example.pitbbcalc.MainActivity" >
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<TextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/title"
android:textAppearance="?android:attr/textAppearanceLarge" />
<Button
android:id="@+id/startButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/start" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<TextView
android:id="@+id/pi_equally"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/pi_equally"
android:textAppearance="?android:attr/textAppearanceLarge" />
<TextView
android:id="@+id/pi_val"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge" />
</LinearLayout>
</LinearLayout>
</RelativeLayout>
In the res/values/strings.xml
add this code:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">PiTBBCalc</string>
<string name="action_settings">Settings</string>
<string name="start">Start</string>
<string name="title">Calculation of π</string>
<string name="pi_equally">π = </string>
</resources>
Now the main activity looks like this:
Next we need to implement the Java* interface for our activity. In the src/intel.example.pitbbcalc/MainActivity.java
file, add the following code:
package intel.example.pitbbcalc;
import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
public class MainActivity extends Activity {
private native double onClickCalc();
private TextView piEqually;
private TextView piVal;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button startButton = (Button) findViewById(R.id.startButton);
piEqually = (TextView) findViewById(R.id.pi_equally);
piVal = (TextView) findViewById(R.id.pi_val);
piEqually.setVisibility(View.INVISIBLE);
piVal.setVisibility(View.INVISIBLE);
startButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
double val = onClickCalc();
piVal.setText(String.valueOf(val));
piEqually.setVisibility(View.VISIBLE);
piVal.setVisibility(View.VISIBLE);
}
});
System.loadLibrary("PiTBBCalc");
System.loadLibrary("tbb");
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
We can add native support by right-clicking on our project in Project Explorer -> Android Tools -> Add Native Support.
On the next window enter the name of the lib of our project and click Finish.
Now we have to implement native code for integral calculating in one thread. In the jni/PiTBBCalc.cpp
file, add the following code:
#include <jni.h>
#include <math.h>
double piIntFunc (const double x)
{
return sqrt(1 - pow(x, 2.0));
}
double calcPi()
{
const unsigned int n = pow(10.0, 7);
double a(-1), b(1);
double h = (b - a) / n;
double x (a);
for (unsigned int i (0); i < n; ++i)
{
sum += piIntFunc(x);
x += h;
}
sum *= h;
return 2 * sum;
}
extern "C"
JNIEXPORT jdouble JNICALL Java_intel_example_pitbbcalc_MainActivity_onClickCalc(JNIEnv *env,
jobject obj)
{
return calcPi();
}
Let’s try running our application and π calculation in single threaded mode.
To add parallel implementation with Intel® TBB to our project we should edit jni/Android.mk
. Android.mk is the Makefile for our project, and we need to add the Intel® TBB libs to it:
LOCAL_PATH := $(call my-dir)
TBB_PATH := <tbb_sources>
TBB_BUILD_PATH := /build/linux_intel64_gcc_android_cc4.9_NDKr10b_version_android-L_release
include $(CLEAR_VARS)
LOCAL_MODULE := PiTBBCalc
LOCAL_SRC_FILES := PiTBBCalc.cpp
LOCAL_CFLAGS += -DTBB_USE_GCC_BUILTINS -std=c++11 -fexceptions -Wdeprecated-declarations -I$(TBB_PATH)/include -I$(TBB_PATH)$(TBB_BUILD_PATH)
LOCAL_LDLIBS := -llog -ltbb -L./ -L$(TBB_PATH)$(TBB_BUILD_PATH)
LOCAL_SHARED_LIBRARIES += libtbb
include $(BUILD_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := libtbb
LOCAL_SRC_FILES := $(TBB_PATH)$(TBB_BUILD_PATH)/libtbb.so
include $(PREBUILT_SHARED_LIBRARY)
In the jni/
directory, create an Application.mk
file and add the following lines:
APP_ABI := x86_64 APP_GNUSTL_FORCE_CPP_FEATURES := exceptions rtti APP_STL := gnustl_shared
The purpose of Application.mk is to describe which native modules (i.e., static/shared libraries) are needed by your application. In the line APP_ABI := x86_64
we specify our target architecture.
Now we can try to run our application. If you see the main screen of the application, then Intel® TBB linked successfully and we can start developing our app.
For adding parallelism to the code, we should include the Intel® TBB header: #include "tbb/tbb.h"
, remove the cycle and add the following code:
double sum = tbb::parallel_reduce(
tbb::blocked_range<unsigned int>(0,n),
double(0), [&](const tbb::blocked_range<unsigned int>& r, double sum)->double {
for( int i=r.begin(); i!=r.end(); ++i )
{
sum += piIntFunc(x);
x += h;
}
return sum; },
[]( double x, double y )->double {
return x+y; }
);
And now, if you run the application it will work in multithreaded mode.
Summary
As you can see, developing parallel applications is very easy. By using the calculation of π as an example we were able to successfully demonstrate how to apply the concepts here from single-threaded code to multithreaded code.
Additional Resources