Android SDK vs NDK - Leistungsvergleich ähnlicher Codeabschnitte

Um die Anwendungsleistung unter Android zu verbessern, begann er, wichtige Codeabschnitte von Java (SDK) nach und nach in C ++ (NDK) umzuschreiben. Das Ergebnis entpuppte sich als vergleichbar mit dem, was ich vor ein paar Jahrzehnten erhalten hatte, als Assembler-Einfügungen in den Turbopascal-Code vorgenommen wurden.

Ich habe mir nicht die Aufgabe gestellt, die Arbeit mit Android NDK zu beschreiben - die Erfahrung selbst reicht nicht aus. Diejenigen , die daran interessiert sind, ist es am besten , mit zu beginnen diesem Link.
Der Zweck dieses kurzen Artikels ist es, ein paar Zahlen anzugeben, die ich empirisch erhalten habe, indem ich die Ausführungszeit bestimmter in Java geschriebener und dann in C ++ umgeschriebener Funktionen verglichen habe. Und vielleicht motivieren diese Zahlen jemanden, sich eingehender mit diesem Thema zu befassen.

Da sich meine Anwendung auf die Fotobearbeitung bezieht, waren die Engpässe Zyklen des Umgehens der Pixel des Bildes und bestimmter Aktionen auf ihnen. Ich habe auf realen Geräten getestet - Nexus One und Nexus 7 (2012). Die Versuchsergebnisse (in ms) sind in Tabellen zusammengefasst:

Ebenenüberlagerung (Helligkeitsmodus, Farbzeichnung)

Nexus einsNexus 7
SDKNdkSDKNdk
2563120485090
21221004520190
21621104330100

Der durchschnittliche Geschwindigkeitsgewinn beim Nexus One beträgt 21-mal, beim Nexus 7-36-mal.

Ebenenüberlagerung (Farbausweichmodus, Monochrom)

Nexus einsNexus 7
SDKNdkSDKNdk
267330572080
257220623070
257320611070

Im Durchschnitt beträgt der Geschwindigkeitszuwachs für das Nexus One das 112-fache, für das Nexus 7 bis 82-fache.

Transparenzverlauf überlagern

Nexus einsNexus 7
SDKNdkSDKNdk
13013213010470
12213302670620
12113002770610

Im Durchschnitt beträgt der Geschwindigkeitsgewinn beim Nexus One das 4-fache, beim Nexus das 7- bis 5-fache.

Wie Sie sehen, unterscheiden sich die Ergebnisse um eine oder sogar zwei Größenordnungen. Ich habe Zahlen in absoluten Zahlen angegeben, damit Sie die tatsächliche Beschleunigung der Arbeit durch den Einsatz von NDK sehen können. Die relativ bescheidenen Ergebnisse des letzten Tests sind darauf zurückzuführen, dass zur Berechnung des Overlays die Standardfunktionen der OpenCV-Bibliothek verwendet wurden, die recht gut optimiert sind. Dementsprechend zeigt dieser Test deutlich die tatsächliche Beschleunigung der Anwendung als Ganzes.

Ich werde auf die Anwendung der OpenCV-Bibliothek eingehen. Wie erwartet ist der Java-Teil der Bibliothek ein regulärer Wrapper über das NDK. Trotzdem führte er die obigen Experimente mit ziemlich schweren und langlebigen Algorithmen durch - wie das Auffinden charakteristischer Punkte in Bildern, Grabcut - eine Methode. Der Geschwindigkeitsunterschied zwischen Java und NDK betrug maximal 10%, was auf den Fehler zurückzuführen ist, da ich zu diesem Zeitpunkt nicht genau die gleichen Bilder erhalten konnte.

Update Es ist ziemlich unangenehm, seine eigenen Fehler zuzugeben, aber was ist zu tun?
Hier ist ein Beispielcode, mit dem ich die Leistung der Java-Implementierung der OpenCV-Bibliothek bewertet habe:
for (int i=0; i255){
			matPix[0] = 255.;
		} else {
			matPix[0] = (255. * matPix[0]) / (256. - topPix[0]);
		}
		mat.put(i, j, matPix);
	}	
}

Wir durchlaufen pixelweise zwei Matrizen gleicher Größe und berechnen abhängig vom Wert des entsprechenden Pixels der einen und der anderen Matrix das resultierende Pixel.
Dank der Kommentare in den Kommentaren zum Artikel wurde der Code wie folgt optimiert (die Abbildungen sind einfarbig):
int size = mat.cols();
byte[] matPix = new byte[size];
byte[] topPix = new byte[size];
for (int i=0; i255){
            mp = 255;
        } else {
            mp = (255 * mp) / (256 - tp);
        }
        matPix[j] = (byte) mp;
    }
    mat.put(i, 0, matPix);
}

Zum Testen habe ich wieder echte Nexus One- und Nexus 7-Geräte verwendet und dem Eingang in beiden Fällen 3-Megapixel-Bilder zugeführt - ich wollte die Leistung der Geräte miteinander vergleichen. Die Ergebnisse (Durchschnitt in ms) sind in der Tabelle zusammengefasst:

Nexus einsNexus 7
SDKNdkSDKNdk
Keine Optimierung3540424522755160
Mit der Optimierung340205210120

Jeder kann selbst Schlüsse ziehen. Die Codeoptimierung in C ++ wurde nach dem gleichen Prinzip wie in Java durchgeführt. Ich habe den Code nicht angegeben, er ist derselbe wie oben.

Jetzt auch beliebt: