Cómo hacer la sincronización correcta del código RenderScript de Android en Nvidia Shield
He implementado una pequeña CNN en RenderScript y quiero perfilar el rendimiento en diferentes hardware. En mi Nexus 7, los tiempos tienen sentido, pero en el NVIDIA Shield no.
El CNN (LeNet) se implementa en 9 capas que residen en una cola, el cálculo se realiza en secuencia. Cada capa se cronometra individualmente.
Aquí hay un ejemplo:
conv1 pool1 conv2 pool2 resh1 ip1 relu1 ip2 softmax
nexus7 11.177 7.813 13.357 8.367 8.097 2.1 0.326 1.557 2.667
shield 13.219 1.024 1.567 1.081 0.988 14.588 13.323 14.318 40.347
La distribución de los tiempos es adecuada para el nexo, con conv1 y conv2 (capas de convolución) que toman la mayor parte del tiempo. Pero en el escudo, los tiempos caen más allá de lo razonable para las capas 2-4 y parecen acumularse hacia el final. La capa softmax es un trabajo relativamente pequeño, por lo que 40 ms es demasiado grande. Mi método de sincronización debe estar defectuoso o algo más está sucediendo.
El código que ejecuta las capas se parece a esto:
double[] times = new double[layers.size()];
int layerindex = 0;
for (Layer a : layers) {
double t = SystemClock.elapsedRealtime();
//long t = System.currentTimeMillis(); // makes no difference
blob = a.forward(blob); // here we call renderscript forEach_(), invoke_() etc
//mRS.finish(); // makes no difference
t = SystemClock.elapsedRealtime() - t;
//t = System.currentTimeMillis() - t; // makes no difference
times[layerindex] += t; // later we take average etc
layerindex++;
}
Tengo entendido que una vez que forEach_ () regresa, se supone que el trabajo está terminado. En cualquier caso, mRS.finish () debería proporcionar una barrera final. Pero mirando los tiempos, la única explicación razonable es que los trabajos aún se procesan en segundo plano.
La aplicación es muy simple, solo ejecuto la prueba desde MainActivity e imprimo en logcat. Android Studio construye la aplicación como una versión y la ejecuta en el dispositivo que está conectado por USB.
(1) ¿Cuál es la forma correcta de cronometrar los procesos de RenderScript? (2) ¿Es cierto que cuando forEach_ () regresa, los hilos generados por el script están garantizados? (3) En mi aplicación de prueba, simplemente ejecuto directamente desde MainActivity. ¿Es este un problema (aparte de bloquear el hilo de la interfaz de usuario y hacer que la aplicación no responda)? Si esto influye en el momento o causa la rareza, ¿cuál es la forma correcta de configurar una aplicación de prueba como esta?