Dies mag offensichtlich klingen, aber Computer führen keine Formeln aus , sie führen Code aus , und wie lange diese Ausführung dauert, hängt direkt von dem Code ab, den sie ausführen, und nur indirekt von dem Konzept, das der Code implementiert. Zwei logisch identische Codeteile können sehr unterschiedliche Leistungsmerkmale aufweisen. Einige Gründe, die bei der Matrixmultiplikation auftreten können:
- Mehrere Threads verwenden. Es gibt kaum eine moderne CPU, die nicht über mehrere Kerne verfügt, viele verfügen über bis zu 8 Kerne, und spezialisierte Computer für Hochleistungs-Computing können problemlos 64 Kerne über mehrere Sockel verteilen. Das offensichtliche Schreiben von Code in einer normalen Programmiersprache verwendet nur eine davon. Mit anderen Worten, es werden möglicherweise weniger als 2% der verfügbaren Computerressourcen des Computers verwendet, auf dem es ausgeführt wird.
- Verwendung von SIMD-Anweisungen (verwirrenderweise wird dies auch als "Vektorisierung" bezeichnet, jedoch in einem anderen Sinne als in den Textzitaten in der Frage). Geben Sie der CPU im Wesentlichen anstelle von 4 oder 8 oder so skalaren Arithmetikbefehlen einen Befehl, der die Arithmetik für 4 oder 8 oder so Register parallel ausführt. Dies kann buchstäblich einige Berechnungen (wenn sie vollkommen unabhängig und für den Befehlssatz geeignet sind) 4 oder 8-mal schneller machen.
- Den Cache intelligenter nutzen . Der Speicherzugriff ist schneller, wenn sie zeitlich und räumlich kohärent sind, dh aufeinanderfolgende Zugriffe erfolgen auf nahe gelegene Adressen, und wenn Sie zweimal auf eine Adresse zugreifen, greifen Sie zweimal schnell hintereinander auf sie zu, anstatt mit einer langen Pause.
- Verwenden von Beschleunigern wie GPUs. Diese Geräte unterscheiden sich stark von CPUs, und ihre effiziente Programmierung ist eine ganz eigene Kunstform. Beispielsweise haben sie Hunderte von Kernen, die in Gruppen von einigen Dutzend Kernen zusammengefasst sind, und diese Gruppen teilen sich Ressourcen - sie teilen sich einige KB Speicher, der viel schneller als normaler Speicher ist, und wenn ein Kern der Gruppe eine ausführt
if
Anweisung alle anderen in dieser Gruppe müssen darauf warten.
- Verteilen Sie die Arbeit auf mehrere Computer (sehr wichtig bei Supercomputern!), Was eine Menge neuer Kopfschmerzen mit sich bringt, aber natürlich den Zugriff auf erheblich größere Computerressourcen ermöglicht.
- Intelligentere Algorithmen. Für die Matrixmultiplikation ist der einfache O (n ^ 3) -Algorithmus, der mit den obigen Tricks optimiert wurde, oft schneller als die subkubischen für angemessene Matrixgrößen, aber manchmal gewinnen sie. Für spezielle Fälle wie dünne Matrizen können Sie spezielle Algorithmen schreiben.
Viele clevere Leute haben sehr effizienten Code für gängige lineare Algebra-Operationen geschrieben , wobei sie die oben genannten und viele weitere Tricks verwendeten und normalerweise sogar plattformspezifische Tricks. Daher profitiert die Umwandlung Ihrer Formel in eine Matrixmultiplikation und die anschließende Implementierung dieser Berechnung durch Aufrufen einer ausgereiften Bibliothek für lineare Algebra von diesem Optimierungsaufwand. Wenn Sie dagegen die Formel einfach auf offensichtliche Weise in einer höheren Sprache ausschreiben, wird der schließlich generierte Maschinencode nicht alle diese Tricks verwenden und ist auch nicht so schnell. Dies gilt auch, wenn Sie die Matrixformulierung nehmen und durch Aufrufen einer von Ihnen selbst erstellten naiven Matrixmultiplikationsroutine implementieren (ebenfalls auf offensichtliche Weise).
Das schnelle Erstellen von Code nimmt Arbeit in Anspruch , und oft ist es ziemlich viel Arbeit, wenn Sie die letzte Unze Leistung wünschen. Da so viele wichtige Berechnungen als Kombination mehrerer linearer Algebraoperationen ausgedrückt werden können, ist es wirtschaftlich, hochoptimierten Code für diese Operationen zu erstellen. Ihr einmaliger spezieller Anwendungsfall? Das interessiert niemanden außer Ihnen, so dass es nicht wirtschaftlich ist, das Ganze zu optimieren.