В недавно вышедшем релизе библиотеки 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/
Добавить комментарий