[Перевод] Вычисление числа Пи с помощью Intel Threading Building Blocks
Многие Android-устройства используют процессоры с несколькими вычислительными ядрами, поэтому в отрасли разработки мобильных приложений всё более важным становится умение создавать многопоточные программы. Компания Intel предлагает ценный инструментарий для разработки «параллельных» приложений — он называется Intel Threading Building Blocks (Intel TBB). По существу, Intel TBB представляет собой кросс-платформенную библиотеку шаблонов для создания параллельных программ. Она позволяет создавать и синхронизировать потоки данных, оставляя за кадром детали архитектуры и позволяя вам работать на высоком уровне абстрагирования. Intel TBB поддерживает все архитектуры. Что касается ОС Android, то следует использовать версию 4.3 и выше.
Создание Intel TBB
Скачайте Intel TBB, найти можно здесь: www.threadingbuildingblocks.org.
Добавьте NDK в PATH. Для Windows:
$ SET PATH=%PATH%;
Для Linux:
$ export PATH=$PATH:
Распакуйте TBB и перейдите в директорию с исходным кодом и в папку src.
$ cd /src/
Запустите TBB для Android:
$ /ndk-build –C /src/ arch=intel64 compiler=gcc target=android clean tbb tbbmalloc –j
Эта команда создает TBB для 64-разрядной версии Android 64. Чтобы сформировать TBB для 32-разрядной версии Android, замените arch=intel64 на arch=ia32.
Библиотека создана. В соответствующей директории (/build/) вы найдете поддиректории с библиотеками: libgnustl_shared.so, libtbbmalloc_proxy.so, libtbbmalloc.so and libtbb.so. libtbb.so и libgnustl_shared. Теперь их можно использовать в нашем приложении.
Вычисление числа Пи
Для вычисления Пи можно выбрать в Wikipedia любую формулу с определенным интегралом. Я выбрал следующую формулу:
Для данной программы я модифицировал эту формулу:
Для вычисления интеграла я использовал метод прямоугольников. Интегрируемая функция разбивается на N = 107 равных подинтервалов длиной h = 2·10–7. Затем вычисляется аппроксимация интеграла — сложением площадей (основание х высоту) N прямоугольников по формуле:
Создание приложения
Создадим новое Android-приложение: 
Создадим «основную активность» (Main Activity). Копируем следующий код в res/layout/activity_main.xml:
А в res/values/strings.xml такой код:
Теперь Main Activity выглядит примерно так: 
Далее нам нужно реализовать для своей активности интерфейс Java. В файл src/intel.example.pitbbcalc/MainActivity.java добавим следующий код:
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) { // TODO автоматически генерируемая заглушка 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) {
// Обработка элементов строки действий. Действия будут
// автоматически обрабатывать щелчки мышью на Home/Up, если
// в AndroidManifest.xml задается родительское действие.
int id = item.getItemId ();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected (item);
}
}
В Project Explorer → Android Tools → Add Native Support можно задать нативную поддержку нажатия правой кнопкой на нашем проекте. В следующем окне вводим имя библиотеки нашего проекта и щёлкаем мышью на Finish.
Итак, мы реализовали нативный код для вычисления интеграла в одном потоке. В файл jni/PiTBBCalc.cpp добавим следующий код:
#include
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 ();
}
Попробуем запустить наше приложение и вычислить число Пи в однопоточном режиме: 
Чтобы с помощью Intel TBB добавить в проект параллельные вычисления, нужно отредактировать jni/Android.mk. Android.mk — это Makefile для нашего проекта, и нужно добавить в него библиотеки Intel TBB:
LOCAL_PATH:= $(call my-dir)
TBB_PATH:=
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) В директории jni/ создадим файл Application.mk и добавим в него следующие строки: APP_ABI:= x86_64 APP_GNUSTL_FORCE_CPP_FEATURES:= exceptions rtti APP_STL:= gnustl_shared Здесь назначение Application.mk состоит в описании необходимых нашему приложению нативных модулей (то есть статический/общих библиотек). В строке APP_ABI:= x86_64 зададим нашу целевую архитектуру.Теперь попробуем запустить приложение. Если вы увидите основной экран приложения, значит библиотеки Intel TBB слинковались успешно, и мы можем начинать разработку нашего приложения.
Для добавления параллелизма нам следует включить заголовок Intel TBB: #include «tbb/tbb.h», удалить цикл и добавить следующий код:
double sum = tbb: parallel_reduce (
tbb: blocked_range
» Threading Building Blocks — базовые элементы многопоточности» Создание параллельных Android-приложений для 64-разрядной архитектуры с использованием Intel TBB» Руководство по Android: написание многопоточных приложений с помощью Intel Threading Building Blocks
