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

в 12:27, , рубрики: android, android development, c++, c++ библиотеки, c++11, intel tbb, intel threading building blocks, tbb, Блог компании Intel, параллельное программирование, Разработка под android, метки: , , , , , , ,

Совсем недавно мы рассматривали написание многопоточных приложений для магазина 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:
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
Коммерческая версия 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

Автор: vpolin

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js