demandé également ici sans chance (https://groups.google.com/forum/#!topic/android-developers/Rh_L9Jv_S8Q)Copie vers et de l'allocation de F16 demi-précision dans Android (renderScript)
J'essaie de comprendre comment faire demi-précision en utilisant des types comme half
et half4
. Le seul problème semble être d'obtenir les nombres de Java à rendu et retour.
Le code 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
Le 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);
}
J'ai aussi essayé cela au lieu de la dernière ligne indiqué dans le code 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 le code ci-dessus fonctionne parfaitement pour float4
variables dans le rendu et F32
allocations dans le java. C'est évidemment parce qu'il n'y a aucun problème allant du rendu float
à Java float
. Mais en essayant d'aller de Java float
(puisqu'il n'y a pas de Java half
) à half
renderscript et de retour est très difficile. Quelqu'un peut-il me dire comment le faire?
Les deux versions ci-dessus du code java résultent en des valeurs apparemment aléatoires dans le tableau half_output
. Ils ne sont évidemment pas aléatoires car ce sont les mêmes valeurs chaque fois que je l'exécute, quelle que soit l'opération dans la fonction half_operation(uint32_t x)
. J'ai essayé de changer le out.x /= 2.0;
(et le code y, z, w correspondant) en out.x /= 2000000.0;
ou out.x *= 2000000.0;
et toujours les valeurs qui finissent dans le tableau half_output
sont les mêmes chaque fois que je l'exécute.
Saisie de 182.24 3.98 105.83 226.08 15.2 80.01...
En utilisant cette java
output3.copy1DRangeToUnchecked(0, dimen * dimen * 3, half_output); //copy F16 allocation back to float array
Le half_output résultant est 46657.44 27094.48 3891.45 965.1825 36223.44 14959.08...
En utilisant cette 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];
}
Le half_output résultant est 2.3476E-41 2.5546E-41 6.2047E-41 2.5407E-41 1.9802E-41 2.4914E-41...
Encore une fois ce sont les résultats, peu importe ce que je change l'algorithme out.x /= 2.0;
à.