2016-05-14 4 views
2

Я реализовал CNN в RenderScript, описанном в previous question, который породил этот. В основном, при работеRenderScript speedup 10x при форсировании реализации ЦП по умолчанию

adb shell setprop debug.rs.default-CPU-driver 1 

существует 10x убыстрение как на Nvidia Shield и Nexus 7. Среднее время вычисления идет от около 50мс 5мс, тест приложение идет от около 50fps до 130 или более. Существует два алгоритма свертки:

(1) движущееся ядро ​​
(2) im2col и GEMM из RenderScriptIntrinsicsBLAS.

Оба опыта аналогичного ускорения. Вопрос в том, почему это происходит и может ли этот эффект быть создан из кода предсказуемым образом? И подробная информация об этом доступна где-то?

Edit:

В соответствии с предложениями ниже, я проверил использование отделки() и CopyTo(), вот разбивка процедуры. Сообщение об ускоренном состоянии происходит после вызова copyTo(), но без финиша(). Uncommenting finish() добавляет около 1 мс к времени.

double forwardTime = 0; 
long t = System.currentTimeMillis(); 
//double t = SystemClock.elapsedRealtime(); // makes no difference 
for (Layer a : layers) { 
    blob = a.forward(blob); 
} 
mRS.finish(); // adds about 1ms to measured time 

blob.copyTo(outbuf); 
forwardTime = System.currentTimeMillis() - t;​ 

Может быть, это не имеет никакого отношения, но на NVIDIA Shield я получаю сообщение об ошибке при запуске, который исчезает при работе с ADB оболочки setprop debug.rs.default-CPU-водитель 1

E/Renderscript: rsAssert failed: 0, in vendor/nvidia/tegra/compute/rs/driver/nv/rsdNvBcc.cpp 

I 'm устанавливает compileSdkVersion, minSdkVersion и targetSdkVersion до 23 прямо сейчас, с buildToolsVersion "23.0.2". Таблетки полностью адаптированы к самой последней версии Android. Не уверен в минимальной цели, которую мне нужно установить и у вас есть ScriptIntrinsicsBLAS.

Я использую #pragma rs_fp_relaxed во всех сценариях. В Allocations используются флаги по умолчанию.
This question имеет аналогичную ситуацию, но оказалось, что OP создает новые объекты Script каждый вычислительный раунд. Я ничего не делаю, все сценарии и распределения создаются во время init.

+1

хммм, это довольно интересно. Shield Tablet и Nexus7 имеют совершенно разные аппаратные средства, но демонстрируют одинаковое поведение. Возможно, вы можете попробовать следующее, чтобы получить дополнительную информацию: 1. Вместо того, чтобы запускать его один раз и получать время, запустите вычисление за 1 или 10 и подсчитайте завершенные итерации, чтобы получить среднее время. 2. Не используйте rs_fp_relaxed и посмотрите, какая разница. 3. Разделите время как исходное сообщение, чтобы увидеть, какая часть больше всего затронута. –

+1

Кроме того, для ScriptIntrinsicsBLAS, если вы используете платформу Renderscript (android.rderscript), то minSDK должно быть 23. Если вы используете поддержку библиотеки RenderScript (android.support.v8.renderscript), то minSdkVersion может быть как 8, так и targetSdkVersion должно быть 23+. Есть несколько настроек для поддержки lib BLAS в будущих buildtools 24.0.0, особенно для BNNM. Но, возможно, лучше иметь отдельный поток для истории поддержки lib и держать это в чистоте. –

ответ

0

Исходный пост имеет mRS.finish() закомментирован. Мне интересно, если это так.

Чтобы правильно измерить RenderScript, мы должны дождаться ожидающих асинхронных сеансов. Существует, как правило, два способа сделать это:

  1. Использование RenderScript.finish(). Это хорошо работает при использовании debug.rs.default-CPU-driver 1. И он также работает с большинством драйверов GPU. Однако некоторые драйверы GPU рассматривают это как NOOP.
  2. Используйте Allocation.copyTo() или другие аналогичные API-интерфейсы для доступа к данным распределения, предпочтительно к окончательному выделению. Это на самом деле трюк, но он работает на всех устройствах. Просто имейте в виду, что сама операция copyTo может занять некоторое время и убедиться, что вы принимаете это во внимание.

5 мс здесь кажется подозрительным, он может быть реальным в зависимости от алгоритма на самом деле. Но стоит дважды проверить, все ли так, когда вы добавляете финиш() или copyTo().

+0

Возможно, немного оффтопик, но есть ли какие-либо ресурсы по спецификациям драйверов GPU для RenderScript? Было бы здорово узнать больше о таких вещах, как то, что вы упомянули о некоторых графических процессорах, обрабатывающих финиш() в качестве noop, или просто о том, какие графические процессоры поддерживают то, что. Разумеется, вся суть RS заключается в том, чтобы избежать фрагментации каждого устройства, но было бы бесценно иметь доступ к такой информации. Любые подсказки о том, как и где мы можем узнать больше о таких деталях? – monoeci

+0

Сообщается, что ускорение включает copyTo(), но не завершает(). Я проверил тест с финишем(), который добавил 1 мс. См. Отредактированный ответ выше. – frankhond

+2

@monoeci, насколько мне известно, в настоящее время отсутствует API, отображающий информацию о том, работает ли определенное ядро ​​RenderScript на графическом процессоре или процессоре или других. Но это большое предложение, которое стоит рассмотреть. С одной стороны, перенастройка для конкретного оборудования будет стоить производительности другим; но с другой стороны, подобная информация в сочетании с некоторыми руководствами и инструментами кодирования значительно поможет продвинутым разработчикам RS, оптимизирующим их код. На данный момент лучшим намеком может быть использование ЦП из «utime» или других полей в «/ proc/self/stat», которое измеряется в типе процессора. –

0

Это очень странно.Тот факт, что вы получаете одинаковый результат на обоих устройствах и с двумя очень разными реализациями conv-слоев, говорит о том, что по-прежнему происходит что-то еще по сравнению с самим бенчмаркингом или временем, а не различиями с выполнением CPU/GPU, поскольку все редко это убедительно.

Я бы предложил проверить, что выходы из экземпляра copyTo() всегда совпадают. Настройте вывод logcat, скажем, первых (и последних!) 10 значений в массиве float, который возвращается из распределения вывода каждого уровня, чтобы убедиться, что все реализации и режимы выполнения действительно обрабатывают данные правильно и одинаково на каждом уровне.

В зависимости от вашей установки также возможно, что упомянутые выше накладные расходы на копирование данных могут привести к превышению времени вычисления, и то, что вы видите, является всего лишь неудачным эффектом этого, поскольку возможно копирование данных из одного места или другой занимает больше или меньше времени. Попытайтесь увеличить размеры или количество ящиков conv (с фиктивными/случайными значениями, просто для тестирования), чтобы сделать вычисления более сложными и тем самым компенсировать баланс времени вычислений и данных и посмотреть, как это влияет на ваши результаты.

Если все остальное терпит неудачу, это может быть просто из-за того, что на какой-то причине GPU действительно занимает больше времени, хотя может быть трудно отследить, почему. Некоторые вещи, чтобы проверить ... Какие типы данных и размер вы используете для данных? Как вы загружаете/записываете данные в распределения? Вы используете #pragma rs_fp_relaxed уже для установки точности ваших поплавков? Какие флаги вы устанавливаете для использования распределения (например, Allocation.USAGE_SCRIPT | Allocation.USAGE_GRAPHICS_TEXTURE)?

И за ваш последний вопрос, подробные RS документации по конкретным вопросам оптимизации еще очень мало, к сожалению ... Я думаю, просто спрашиваю здесь на SO еще один из лучших ресурсов, доступная на данный момент :)

+0

Я использую #pragma rs_fp_relaxed во всех сценариях. В Allocations используются флаги по умолчанию. Добавлена ​​некоторая дополнительная информация о системе для вопросов, может быть, мне нужно настроить цель по-другому? – frankhond

+0

Хм, у меня нет идей, потом помогите, извините. Если другие вещи выше не помогают, возможно, попытайтесь сломать проблему.Вместо того, чтобы запускать полный CNN, выполните более простой процесс (например, одну свертку) и убедитесь, что вы получаете ускорение на графическом процессоре, а затем медленно добавляйте обратно в различные другие части для полного CNN, пока не найдете виновника. К сожалению, это иногда единственный способ сделать то, что у нас пока нет надлежащего профилировщика для RS, как мы делаем для OpenCL или других API-интерфейсов GPU. Надеюсь, вы найдете проблему, и если да, пожалуйста, сообщите мне об этом, я буду очень рад услышать, что вы найдете. – monoeci

+0

Я попытаюсь создать новый проект с простым воспроизводимым футляром. Это может занять несколько дней, я вернусь сюда с результатом. В то же время, вы думаете, что currentTimeMillis() или elapsedRealTime() надежны для измерения времени настенных часов в этом случае? – frankhond

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

  • Нет связанных вопросов^_^