2013-04-08 2 views
4

Я выполнил простой параллельный алгоритм, нарисовав набор mandelbrot для тестирования параллельных вычислений на Nexus 7 (ядра Tegra 3, 4 + 1). После запуска несколько раз я получаю 1,5 секунды для последовательного и 1,0 для параллельных, но параллельные и последовательные приходят очень близко друг к другу на 1,3 секунды.Многоядерный Android

Квадрат 700x700 пикселей, а код Мандельброта я использую из

http://rosettacode.org/wiki/Mandelbrot_set#Java

Параллельная реализация проходит две половинки Мандельброта, как это

public void mandelbrotParallel() { 
    Thread t1 = new Thread(new Runnable() { 
     public void run() { 
      mandelbrotOne(); 
     } 
    }); 
    Thread t2 = new Thread(new Runnable() { 
     public void run() { 
      mandelbrotTwo(); 
     } 
    }); 
    t1.start(); 
    t2.start(); 
    try { 
     t1.join(); 
     t2.join(); 
    } catch (InterruptedException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } 
    mHandler.post(new Runnable() { 
     public void run() { 
      v.setBmp(bmp); 
      v.invalidate(); 
     } 
    }); 
} 

Я запустить простой вектор дополнение до и нашел похожие анекдотические результаты (без научной строгости). Поэтому мне интересно, есть ли что-то особенное, чтобы заставить Android запускать несколько ядер, чтобы выполнить задание.

Основываясь на быстрых разговорах с Google, возможно, что ядра неактивны и ждут, что вычисление будет действительно длительным (несколько секунд) до включения сердечников ... Это правда? Если да, существуют ли API-вызовы от Java (нет JNI), которые можно выполнить для предварительного пробуждения ядер?

+1

Некоторое время назад я бросил http://bigflake.com/cpu-spinner.c.txt вместе, как способ оценки того или не будить сердечники up когда внизу груз. Вообще говоря, ядра замедляются или отключаются, чтобы сохранить время автономной работы, и только «развернуться», когда ядро ​​обнаруживает многоядерную нагрузку. Задержка отжима зависит от устройства. Для справки, на моем Nexus 4 тест закончился в ~ 1700 мс с 1 нитью и ~ 1800 мс с 4 потоками, что указывает на то, что все ядра были использованы вскоре после начала теста. – fadden

ответ

2

Это звучит как кандидат на RenderScript. В двух словах он позволяет выполнять дорогостоящие вычисления, которые используют все доступные ресурсы ускорения (несколько ядер, вычисление графического процессора, dsp и т. Д.). Из документов:

Renderscript предоставляет вашим приложениям возможность запускать операции с автоматическим распараллеливанием на всех доступных процессорных ядрах. Он также поддерживает различные типы процессоров, таких как CPU, GPU или DSP. Renderscript полезен для приложений, которые выполняют обработку изображений, математическое моделирование или любые операции, требующие большого количества математических вычислений .

Вам нужно будет переписать свой код Мандельброта на C, но вам не придется разбивать его на части, так как вам будет позаботиться о распараллеливании.

Использование кода RenderScript с Android прямолинейно, как описано here.

+1

(Я один из инженеров RS.) Посмотрите в AOSP - frameworks/base/graphics/RenderScriptTests/ImageProcessing содержит реализацию Mandelbrot, которую я написал. Должен дать вам хорошее представление о том, с чего начать. –

2

A нормальный Система Android пытается быть консервативной. Поэтому, если вы создаете новый поток и начинаете некоторые тяжелые вычисления, ядро ​​Linux сначала запускается на одном ядре и увеличивает его базовую скорость. Как только ядро ​​«занято» на некоторое время на некоторое время, только тогда ядро ​​запускает другое ядро.

То же самое верно в другом направлении: как только система успокоится, она медленно отключит сердечники и уменьшит частоту.

С точки зрения разработчика, вы не можете повлиять на это на «нормальном» Android. Android не имеет API для пробуждения определенного количества ядер или установки определенной частоты ядра.


Если вы можете переключиться на коренится Android, у вас есть больше возможностей, так как регулярное ядро ​​Linux имеет возможности оказывать влияние на основные частоты и количества активных ядер. Это делается через «губернаторов». В обычном ядре Linux есть несколько вариантов.По этому вопросу вы заинтересованы в настройке регулятора , который будет поддерживать бодрствование и на самой высокой частоте.

Интерфейс ядра Linux находится в файловой системе /sys. Я собираюсь показать команды adb здесь и оставить его вам, чтобы превратить его в Java, открыть, прочитать и написать команды.

cd /sys/devices/system/cpu 

В этом каталоге вы найдете виртуальные файлы, которые показывают, сколько ядер в системе присутствуют:

cat possible 

должен дать ответ 0-3 в вашем случае Tegra 3. Ядро не знает, что если работает только одно ядро, он тайно переходит к запасному маломощному ядру. Есть также каталоги cpu0 cpu1 cpu2 cpu3. В зависимости от версии ядра они могут появляться только в том случае, если ядро ​​активировано. В каждой директории cpu содержится каталог cpufreq, где вы можете взаимодействовать с cpufreq subsystem. Он должен содержать файл scaling_available_governors, который показывает, какие cpu governors доступны. только на корневую систему, вы можете сделать:

echo "performance" >cpu0/cpufreq/scaling_governor 

Для того, чтобы установить губернатор, который будет держать ядро ​​работает на максимальной частоте. В ненарушенной системе вы получите сообщение об ошибке «разрешено».


Чтобы показать влияние этого поведения, Vector Fabrics создал тестовое приложение, которое выполняет алгоритм inpainting на OpenCV параллельно. Приложение измеряет как последовательные, так и параллельные характеристики до 4 ядер. Даже при параллельной работе параллельной версии измерения меняются в зависимости от запуска сердечников. Посмотрите на себя (скачать сформировать магазин приложений): http://www.vectorfabrics.com/products/case-study/opencv_inpaint

Смежные вопросы