So korrigieren Sie das Timing von Android-RenderScript-Code auf Nvidia Shield
Ich habe einen kleinen CNN in RenderScript implementiert und möchte die Leistung auf unterschiedlicher Hardware darstellen. Auf meinem Nexus 7 machen die Zeiten Sinn, auf dem NVIDIA Shield aber nicht.
Das CNN (LeNet) ist in 9 Schichten implementiert, die sich in einer Warteschlange befinden. Die Berechnung erfolgt nacheinander. Jede Ebene wird einzeln zeitgesteuert.
Hier ist ein Beispiel
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
Die Verteilung der Zeiten ist für den Nexus ungefähr richtig, wobei conv1 und conv2 (Convolution Layer) die meiste Zeit in Anspruch nehmen. Aber auf dem Schild fallen die Zeiten weit über das für die Schichten 2 bis 4 Vernünftige hinaus und scheinen sich gegen Ende zu sammeln. Die Softmax-Schicht ist eine relativ kleine Aufgabe, daher sind 40 ms viel zu groß. Meine Timing-Methode muss fehlerhaft sein oder es ist etwas anderes los.
Der Code, der die Ebenen ausführt, sieht ungefähr so aus:
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++;
}
ach meinem Verständnis soll der Job beendet sein, sobald forEach_ () zurückkehrt. In jedem Fall sollte mRS.finish () eine letzte Barriere darstellen. Aus heutiger Sicht ist die einzige vernünftige Erklärung, dass Jobs immer noch im Hintergrund verarbeitet werden.
Die App ist sehr einfach, ich führe nur den Test von MainActivity aus und drucke auf logcat. Android Studio erstellt die App als Release und führt sie auf dem Gerät aus, das über USB angeschlossen ist.
(1) Was ist der richtige Weg, um RenderScript-Prozesse zeitlich zu steuern? (2) Stimmt es, dass bei der Rückkehr von forEach_ () die vom Skript erzeugten Threads garantiert ausgeführt werden? (3) In meiner Test-App starte ich einfach direkt von der MainActivity aus. Ist dies ein Problem (außer das Blockieren des UI-Threads und das Deaktivieren der App)? Wenn dies das Timing beeinflusst oder die Verrücktheit verursacht, wie kann man eine Test-App wie diese einrichten?