- PVSM.RU - https://www.pvsm.ru -

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

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

В недавно вышедшем релизе библиотеки Intel® TBB tbb41_20121112oss, который доступен для загрузки на нашем сайте threadingbuildingblocks.org [3], добавлена экспериментальная поддержка приложений для 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:
Android: Написание многопоточных приложений с помощью Intel® Threading Building Blocks

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

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

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

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

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

Автор: vpolin

Источник [8]


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/android-development/23229

Ссылки в тексте:

[1] написание многопоточных приложений для магазина Windows: http://habrahabr.ru/company/intel/blog/158263/

[2] Intel® TBB: http://threadingbuildingblocks.org/

[3] threadingbuildingblocks.org: http://threadingbuildingblocks.org

[4] software.intel.com/en-us/intel-tbb: http://software.intel.com/en-us/intel-tbb

[5] software.intel.com/en-us/tags/17207: http://software.intel.com/en-us/tags/17207

[6] software.intel.com/en-us/tags/17220: http://software.intel.com/en-us/tags/17220

[7] software.intel.com/en-us/forums/intel-threading-building-blocks: http://software.intel.com/en-us/forums/intel-threading-building-blocks

[8] Источник: http://habrahabr.ru/post/161527/