Android: Warum ist nativer Code so viel schneller als Java-Code?

8

In der folgenden SO Frage: Ссылка behauptet @zeh einen Port von Ein Java Blur-Algorithmus zu C läuft 40 mal schneller.

Da der Großteil des Codes nur Berechnungen enthält und alle Zuweisungen nur "einmal" vor dem eigentlichen Algorithmus-Zahlen-Crunching erfolgen, kann jemand erklären, warum dieser Code 40-mal schneller läuft? Sollte der Dalvik JIT nicht den Bytecode übersetzen und die Lücke zur nativen kompilierten Code-Geschwindigkeit drastisch reduzieren?

Hinweis: Ich habe den x40-Leistungsgewinn für diesen Algorithmus nicht selbst bestätigt, aber alle ernsthaften Bildbearbeitungsalgorithmen, die ich für Android treffe, verwenden den NDK - dies unterstützt die Vorstellung, dass NDK-Code viel schneller läuft.

>     
Guy 28.01.2014, 07:21
quelle

2 Antworten

13

Bei Algorithmen, die über Datenfelder arbeiten, gibt es zwei Dinge, die die Leistung zwischen einer Sprache wie Java und C erheblich verändern:

  • Überprüfung der Array-Grenze - Java prüft jeden Zugriff, bmap [i], und bestätigt, dass i innerhalb der Array-Grenzen liegt. Wenn der Code versucht, außerhalb der Grenzen zuzugreifen, erhalten Sie eine nützliche Ausnahme. C & amp; C ++ überprüfe nichts und vertraue nur deinem Code. Die bestmögliche Antwort auf einen Zugriff außerhalb der Grenzen ist ein Seitenfehler. Ein wahrscheinlicheres Ergebnis ist "unerwartetes Verhalten".

  • Zeiger - Sie können die Operationen mithilfe von Zeigern erheblich reduzieren.

Nehmen Sie dieses unschuldige Beispiel eines gewöhnlichen Filters (ähnlich wie Unschärfe, aber 1D):

%Vor%

Wenn Sie auf ein Array-Element zugreifen, ist coef [k]:

  • Laden Sie die Adresse des Array Coef in das Register
  • Laden Sie den Wert k in ein Register
  • summiere sie
  • geh an diese Adresse

Jeder dieser Array-Zugriffe kann verbessert werden, weil Sie wissen, dass die Indizes sequenziell sind. Der Compiler, noch das JIT, kann wissen, dass die Indizes sequentiell sind, so dass sie nicht vollständig optimiert werden können (obwohl sie es weiterhin versuchen).

In C ++ würden Sie Code eher so schreiben:

%Vor%

Wenn Sie zuerst so etwas machen (und es schaffen, es richtig zu machen), werden Sie überrascht sein, wie viel schneller es sein kann. Alle Array-Adressberechnungen zum Abrufen des Index und zum Summieren der Index- und Basisadresse werden durch eine Inkrementierungsanweisung ersetzt.

Bei 2D-Array-Operationen, z. B. Unschärfen auf einem Bild, handelt es sich bei unschuldigen Codedaten [r, c] um zwei Wertabholungen, eine Multiplikation und eine Summe. Bei 2D-Arrays können Sie mit den Vorteilen von Zeigern Mehrfachoperationen entfernen.

Die Sprache ermöglicht also eine echte Reduzierung der Operationen, die die CPU ausführen muss. Die Kosten sind, dass der C ++ Code schrecklich zu lesen und zu debuggen ist. Fehler in Zeigern und Pufferüberläufen sind Nahrung für Hacker. Aber wenn es um rohe Zahlenschleifalgorithmen geht, ist die Geschwindigkeitsverbesserung zu verlockend, um sie zu ignorieren.

    
jdr5ca 28.01.2014, 08:53
quelle
-9

Nachfolgend finden Sie eine Liste der Programmiersprachen auf der Grundlage der Ebenen

  • Assemblersprache (Maschinensprache, Liebhaberlevel)
  • C Sprache (mittlere Ebene)
  • C ++, Java, .net, (höhere Ebene)

Hier hat Sprache der unteren Ebene direkten Zugriff auf die Hardware. Solange der Level erhöht wird, sinkt der Zugriff auf die Hardware. Der Code der Assembly-Sprache wird also mit der höchsten Geschwindigkeit ausgeführt, während der Code der anderen Sprache basierend auf ihren Ebenen ausgeführt wird.

Aus diesem Grund läuft der Code von C Language viel schneller als der Java-Code.

    
Lucifer 28.01.2014 07:32
quelle