Чтобы сформулировать свой вопрос:Рекомендуемый подход для вычисления над произвольным размером 3D объем
Я пишу пользовательскую свертку (для CNN), где произвольный размер входной объем ВхШхГ сворачивается с FxFxD фильтром. D может быть 3 или 4, но и намного больше. Я новичок в RenderScript и в настоящее время исследую подходы с целью создания рамки, которая может быть использована в будущем, поэтому я не хочу в конечном итоге использовать API таким образом, который может скоро обесцениться. Сейчас я нацеливаюсь на 23, но, возможно, в какой-то момент вам нужно будет вернуться к 18-19, это обсуждается.
Похоже, что если я определяю 3D-распределение и использую float как тип для in-parameter в ядре, ядро посещает каждый элемент, также по оси Z. Как это:
Ядро:
void __attribute__((kernel)) convolve(float in, uint32_t x, uint32_t y, uint32_t z){
rsDebug("x y z: ", x, y, z);
}
Java:
Allocation in;
Type.Builder tb = new Type.Builder(mRS, Element.F32(mRS));
Type in_type = tb.setX(W).setY(H).setZ(D).create();
in = Allocation.createTyped(mRS, in_type);
//...
mKonvoScript.forEach_convolve(in);
С W = H = 5 и D = 3 есть 75 плавает в 3D-объеме. Запуск программы печатает 75 выходов:
х: {0,000000, 0,000000, 0,000000} х: {1,000000, 0,000000, 0,000000} ... х: {0,000000, 0,000000, 1,000000} х: {1,000000, 0.000000, 1.000000} ...
т.д.
картина повторяется 3х25 раз.
OTOH ссылка неясна относительно z-координаты, и ответ на renderscript: accessing 'z' coordinate гласит, что параметры z-координаты не поддерживаются.
Также мне нужно привязать фильтр к переменной rs_allocation внутри ядра. Сейчас у меня есть:
ядра:
rs_allocation gFilter;
//...
float f = rsGetElementAt_float(gFilter, 1,2,3);
Java:
Allocation filter;
Type filter_type = tb.setX(F).setY(F).setZ(D).create();
filter = Allocation.createTyped(mRS, filter_type);
Это, кажется, не хорошо работать (не компиляции или во время выполнения ошибок). НО есть запись SE, сделанная с 2014 года, в которой говорится, что из версии 20 и вперед мы можем привязывать только 1D-распределения, что противоречит моим результатам.
Существует много противоречивой и устаревшей информации, поэтому я надеюсь, что кто-то изнутри сможет прокомментировать это и рекомендовать подход как с точки зрения устойчивости, так и с точки зрения оптимальности.
(1) Должен ли я идти вперед и использовать переданные координаты xyz для вычисления свертки с привязкой 3D-привязки? Или этот подход станет устаревшим в какой-то момент?
(2) Существуют и другие способы сделать это, например, я могу изменить все распределения на 1D, передать их в ядро и использовать индексную арифметику. Это также позволило бы установить некоторые значения близко друг к другу. Другим подходом может быть разделение входных трехмерных томов на блоки с глубиной 4 и использование float4 как в типе. Предполагая, что (1) можно использовать, с точки зрения оптимизации, есть ли недостаток в использовании (1) в отличие от других подходов?
(3) Как правило, существует желательная формулировка макета памяти, например, для переформулировки проблемы в глубинах float3 или float4 по соображениям оптимальности, в отличие от «простого» подхода, такого как (1)?