Android: Написание многопоточных приложений с помощью Intel® Threading Building Blocks

от автора

Совсем недавно мы рассматривали написание многопоточных приложений для магазина Windows с помощью Intel® Threading Building Blocks(Intel® TBB). Там утверждается, что использование кроссплатформенной библиотеки TBB позволяет легко переносить вычислительную часть на другие платформы. Android как раз сгодится для хорошего примера одной из «других платформ», подробности под катом.

В недавно вышедшем релизе библиотеки Intel® TBB tbb41_20121112oss, который доступен для загрузки на нашем сайте threadingbuildingblocks.org, добавлена экспериментальная поддержка приложений для Android, т.е. построение нативных библиотек для использования Android приложениями через JNI интерфейс.

Для построения библиотеки будем использовать Android SDK Tools Rev.21 и Android NDK Rev 8C. Но тут необходимо оговориться, что, как оказалось при подготовке материала, сказалась экспериментальность и построение самих библиотек в этом релизе. «Из коробки» работает только под NDK на Linux. Мы поправим это в одном из следующих обновлений. Я подпилил немного makefile для Windows и построил библиотеку там, но для простоты будем подразумевать, что сама библиотека была построена на Linux, а всё остальное сделано на Windows. В общем, налицо еще одно преимущество кроссплатформенной библиотеки.

Итак, что же необходимо сделать, чтобы собрать простое приложение с использованием Intel TBB.
Для начала необходимо распаковать и откомпилировать библиотеку, поскольку этот релиз распространяется только в исходниках. Подразумевается, что есть gnu make, в командной строке с выставленным окружением для NDK выполняем команду

gmake tbb tbbmalloc target=android 

Со стороны библиотеки всё, переходим в Eclipse. При помощи шаблонов создаем простое приложение и, для простоты, как в предыдущем случае назовём его app1:

Activity выберем FullscreenActivity. На этом работа шаблона завершится. Обратите внимание, что com.example* приложения не приветствуются магазином гугл. Но для примера вполне сойдет.

Затем добавим пару кнопок на основной фрейм. После этого 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("tbb"); 		System.loadLibrary("jni-engine");		 	} 

Если с библиотекой «tbb» должно быть всё понятно, то на «jni-engine» нужно остановиться подробнее.

«jni-engine» — это С++ библиотека, которая реализует вычислительную часть и выставляет С-интерфейсы для JNI вызовов onClickSRCall() и onClickSRCall().

Согласно правилам разработки внутри проекта создаем каталог ‘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 := 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(); } 

Как видно, используем те же алгоритмы, что и в предыдущем блоге.

При построении с помощью NDK он сам раскладывает библиотеки в нужные каталоги, в том числе libjni-engine.so и libtbb.so.

Теперь переходим обратно в eclipse и строим .apk файл. Приложение готово для установки на AVD или на устройство. Вот так это выглядит на AVD:

Вот и всё! Наше простое приложение написано! А для тех, кто использовал код предыдущего блога, приложение успешно перенесено на Android.

Для тех, кто заинтересовался, пробуйте:

Скачать библиотеку Intel® Threading Building Blocks (Версия с открытым исходным кодом):
threadingbuildingblocks.org
Коммерческая версия Intel® TBB (функционально не отличается):
software.intel.com/en-us/intel-tbb

Англоязычные и русскоязычные блоги об Intel® TBB
software.intel.com/en-us/tags/17207
software.intel.com/en-us/tags/17220
Ну и, конечно, наш форум,
software.intel.com/en-us/forums/intel-threading-building-blocks

ссылка на оригинал статьи http://habrahabr.ru/company/intel/blog/161527/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *