спросил Также здесь не повезло (https://groups.google.com/forum/#!topic/android-developers/Rh_L9Jv_S8Q)Копирование с половинной точности распределения F16 в андроида (Renderscript)
Я пытаюсь выяснить, как сделать половину точности с использованием типов, как half
и half4
. Кажется, что единственная проблема заключается в получении чисел от java до renderscript и обратно.
Java-код:
private float[] input;
private float[] half_output;
private RenderScript mRS;
private ScriptC_mono mScript;
private final int dimen = 15;
...
//onCreate
input = new float[dimen * dimen * 3]; //later loaded from file 182.24 3.98 105.83 226.08 15.2 80.01...
half_output = new float[dimen * dimen * 3];
...
//function calling renderscript
mRS = RenderScript.create(this);
ScriptC_halfPrecision mScript = new ScriptC_halfPrecision(mRS);
Allocation input2 = Allocation.createSized(mRS, Element.F16(mRS), dimen * dimen * 3);
input2.copyFromUnchecked(input); //copy float values to F16 allocation
Allocation halfIndex = Allocation.createSized(mRS, Element.F16(mRS), dimen * dimen);
Type.Builder half_output_type = new Type.Builder(mRS, Element.F16(mRS)).setX(dimen * dimen * 3);
Allocation output3 = Allocation.createTyped(mRS, half_output_type.create());
mScript.set_half_in(input2);
mScript.set_half_out(output3);
mScript.forEach_half_operation(halfIndex);
output3.copy1DRangeToUnchecked(0, dimen * dimen * 3, half_output); //copy F16 allocation back to float array
Renderscript:
#pragma version(1)
#pragma rs java_package_name(com.example.android.rs.hellocompute)
rs_allocation half_in;
rs_allocation half_out;
half __attribute__((kernel)) half_operation(uint32_t x) {
half4 out = rsGetElementAt_half4(half_in, x);
out.x /= 2.0;
out.y /= 2.0;
out.z /= 2.0;
out.w /= 2.0;
rsSetElementAt_half4(half_out, out, x);
}
Я также попытался это вместо последней строки, показанной в коде Java:
float temp_half[] = new float[1];
for (int i = 0; i < dimen * dimen * 3; ++i) { //copy F16 allocation back to float array
output3.copy1DRangeToUnchecked(i, 1, temp_half);
half_output[i]=temp_half[0];
}
Al l приведенный выше код отлично работает для float4
переменных в значениях renderscript и F32
в java. Это, очевидно, связано с тем, что проблема не возникает из renderscript float
в java float
. Но попытка перейти от java float
(так как нет java half
) для renderscript half
и обратно очень сложно. Может ли кто-нибудь сказать мне, как это сделать?
Оба вышеуказанных варианта кода Java приводят к кажущимся случайным значениям в массиве half_output
. Они, очевидно, не являются случайными, потому что они являются одинаковыми значениями каждый раз, когда я запускаю его, независимо от того, какая операция в функции half_operation(uint32_t x)
. Я попытался изменить out.x /= 2.0;
(и соответствующие y, z, w код) на out.x /= 2000000.0;
или out.x *= 2000000.0;
, и все же значения, которые входят в массив half_output
, одинаковы при каждом запуске.
Используя вход 182.24 3.98 105.83 226.08 15.2 80.01...
С помощью этого Java
output3.copy1DRangeToUnchecked(0, dimen * dimen * 3, half_output); //copy F16 allocation back to float array
Полученный half_output является 46657.44 27094.48 3891.45 965.1825 36223.44 14959.08...
С помощью этого Java
float temp_half[] = new float[1];
for (int i = 0; i < dimen * dimen * 3; ++i) { //copy F16 allocation back to float array
output3.copy1DRangeToUnchecked(i, 1, temp_half);
half_output[i]=temp_half[0];
}
Полученный half_output является 2.3476E-41 2.5546E-41 6.2047E-41 2.5407E-41 1.9802E-41 2.4914E-41...
Снова это результаты независимо от того, что я изменяю алгоритм out.x /= 2.0;
.