Der leistungsfähigste Weg, um ein Array von einem anderen zu subtrahieren

8

Ich habe den folgenden Code, der der Engpass in einem Teil meiner Anwendung ist. Ich ziehe nur Array von einem anderen ab. Beide Arrays haben mehr um 100000 Elemente. Ich versuche einen Weg zu finden, dies leistungsfähiger zu machen.

%Vor%

Hat jemand einen Vorschlag?

    
Michael Küller 15.02.2011, 19:58
quelle

5 Antworten

5

Ich war sehr neugierig auf die Geschwindigkeitsoptimierung in diesem einfachen Fall. Also habe ich 6 einfache Prozeduren gemacht und CPU Tick und Zeit bei Array 100000 gemessen;

  1. Pascal-Prozedur mit Compileroption Bereichs- und Überlaufprüfung ein
  2. Pascal-Prozedur mit der Compileroption Range and Overflow Checking off
  3. Klassisches x86-Assembler-Verfahren.
  4. Assembler-Prozedur mit SSE-Anweisungen und nicht ausgerichtete 16-Byte-Verschiebung .
  5. Assembler-Prozedur mit SSE-Anweisungen und ausgerichteter 16-Byte-Verschiebung .
  6. Assembler 8 mal entrollte Schleife mit SSE-Befehlen und ausgerichteter 16-Byte-Verschiebung .

Überprüfen Sie die Ergebnisse auf Bild und Code für weitere Informationen.

Um eine 16-Byte-Speicherausrichtung zu erhalten, löschen Sie zuerst den Punkt in der Datei 'FastMM4Options.inc' Direktive {$ .define Align16Bytes} !

%Vor%

...

Die schnellste ASM-Prozedur mit 8 mal entrollten SIMD-Befehlen benötigt nur 68us und ist etwa 4 mal schneller als die Pascal-Prozedur.

Wie wir sehen können, ist die Pascal-Schleife-Prozedur wahrscheinlich nicht kritisch, es dauert nur etwa 277 us (Überlauf und Bereichsprüfung aus) bei 2,4 GHz CPU bei 100000 Subtraktionen.

Also kann dieser Code kein Engpass sein?

    
GJ. 17.02.2011, 17:15
quelle
9

Wird dies auf mehreren Threads ausgeführt, wird die lineare Beschleunigung mit diesem großen Array erreicht. Es ist peinlich parallel wie sie sagen.

    
David Heffernan 15.02.2011 20:08
quelle
9
___ qstnhdr ___ Der leistungsfähigste Weg, um ein Array von einem anderen zu subtrahieren ___ answer5032215 ___

Ich war sehr neugierig auf die Geschwindigkeitsoptimierung in diesem einfachen Fall. Also habe ich 6 einfache Prozeduren gemacht und CPU Tick und Zeit bei Array 100000 gemessen;

  1. Pascal-Prozedur mit Compileroption Bereichs- und Überlaufprüfung ein
  2. Pascal-Prozedur mit der Compileroption Range and Overflow Checking off
  3. Klassisches x86-Assembler-Verfahren.
  4. Assembler-Prozedur mit SSE-Anweisungen und nicht ausgerichtete 16-Byte-Verschiebung .
  5. Assembler-Prozedur mit SSE-Anweisungen und ausgerichteter 16-Byte-Verschiebung .
  6. Assembler 8 mal entrollte Schleife mit SSE-Befehlen und ausgerichteter 16-Byte-Verschiebung .

Überprüfen Sie die Ergebnisse auf Bild und Code für weitere Informationen.

Um eine 16-Byte-Speicherausrichtung zu erhalten, löschen Sie zuerst den Punkt in der Datei 'FastMM4Options.inc' Direktive {$ .define Align16Bytes} !

%Vor%

...

Die schnellste ASM-Prozedur mit 8 mal entrollten SIMD-Befehlen benötigt nur 68us und ist etwa 4 mal schneller als die Pascal-Prozedur.

Wie wir sehen können, ist die Pascal-Schleife-Prozedur wahrscheinlich nicht kritisch, es dauert nur etwa 277 us (Überlauf und Bereichsprüfung aus) bei 2,4 GHz CPU bei 100000 Subtraktionen.

Also kann dieser Code kein Engpass sein?

    
___ antwort5009386 ___

Das Ausführen von Subtraktionen bei mehr Threads hört sich gut an, aber 100K Integer-Sunstraction brauchen nicht viel CPU-Zeit, also vielleicht threadpool ... Allerdings haben Einstellungs-Threads auch eine Menge Overhead, so dass kurze Arrays eine geringere Produktivität parallel haben Threads als in nur einem (Haupt-) Thread!

Haben Sie in Compiler-Einstellungen, Überlauf und Bereichsüberprüfung ausgeschaltet?

Sie können versuchen, asm Rutine zu verwenden, es ist sehr einfach ...

Etwas wie:

%Vor%

Es kann viel schneller sein ...

BEARBEITEN: Prozedur mit SIMD-Anweisungen hinzugefügt. Diese Prozedur fordert SSE-CPU-Unterstützung an. Es kann 4 ganze Zahlen im XMM-Register annehmen und sofort subtrahieren. Es gibt auch die Möglichkeit, movdqa anstelle von movdqu zu benutzen, es ist schneller, aber Sie müssen zuerst eine 16-Byte-Ausrichtung sicherstellen. Sie können auch die XMM Par wie in meinem ersten Asm-Fall aufheben. (Ich bin interessant über Geschwindigkeitsmessung. :))

%Vor%     
___ answer5011261 ___

Ich bin kein Assembly-Experte, aber ich denke, die folgenden Punkte sind nahezu optimal, wenn Sie SIMD-Anweisungen oder Parallelverarbeitung nicht berücksichtigen, die letztere kann leicht erreicht werden, indem Teile des Arrays an die Funktion übergeben werden.

>

wie
Thread1: SubArray (ar1 [0], ar2 [0], 50); Thread2: SubArray (ar1 [50], ar2 [50], 50);

%Vor%     
___ answer5013976 ___

Es ist keine echte Antwort auf Ihre Frage, aber ich würde untersuchen, ob ich die Subtraktion bereits zu einem bestimmten Zeitpunkt durchführen könnte , während die Arrays mit Werten füllt. Ich würde optional sogar ein drittes Array in dem Speicher betrachten, um das Ergebnis der Subtraktion zu speichern. In der modernen Computertechnik sind die "Kosten" des Speichers erheblich niedriger als die "Kosten" der Zeit, die benötigt wird, um eine zusätzliche Speicheraktion auszuführen.

Theoretisch werden Sie zumindest etwas Leistung erzielen, wenn die Subtraktion durchgeführt werden kann, während sich die Werte noch in Registern oder im Prozessor-Cache befinden. In der Praxis stößt man jedoch auf einige Tricks, die die Leistung des gesamten Algorithmus verbessern könnten .

    
___ qstntxt ___

Ich habe den folgenden Code, der der Engpass in einem Teil meiner Anwendung ist. Ich ziehe nur Array von einem anderen ab. Beide Arrays haben mehr um 100000 Elemente. Ich versuche einen Weg zu finden, dies leistungsfähiger zu machen.

%Vor%

Hat jemand einen Vorschlag?

    
___ tag123x86 ___ x86 ist eine Architektur, die von der Intel 8086 CPU abgeleitet ist. Die x86-Familie umfasst die 32-Bit-Architektur IA-32 und 64-Bit x86-64 sowie 16-Bit-Legacy-Architekturen. Fragen zu letzterem sollten mit [x86-16] und / oder [emu8086] getaggt werden. Verwenden Sie das Tag [x86-64], wenn Ihre Frage für 64-Bit x86-64 spezifisch ist. Verwenden Sie für die x86-FPU das Tag [x87]. Für SSE1 / 2/3/4 / AVX * verwenden Sie auch [sse] und alle zutreffenden [avx] / [avx2] / [avx512] ___ tag123delphi ___ Delphi ist eine Sprache für die schnelle Entwicklung von nativen Windows-, macOS-, Linux-, iOS- und Android-Anwendungen mithilfe von Object Pascal. Der Name bezieht sich sowohl auf die Delphi-Sprache als auch auf deren Bibliotheken, Compiler und IDE, mit denen Delphi-Projekte bearbeitet und debuggt werden können. ___ tag123performance ___ Für Fragen zur Messung oder Verbesserung der Code- und Anwendungseffizienz. ___ tag123sse ___ SSE (Streaming SIMD Extensions) war die erste von vielen ähnlich benannten Vektorerweiterungen für den x86-Befehlssatz. Zu diesem Zeitpunkt ist SSE im Allgemeinen häufiger ein Catch-All für x86-Vektorbefehle und kein Verweis auf SSE ohne SSE2, SSE3 usw. ___ answer5008932 ___

Wird dies auf mehreren Threads ausgeführt, wird die lineare Beschleunigung mit diesem großen Array erreicht. Es ist peinlich parallel wie sie sagen.

    
___
GJ. 15.02.2011 20:55
quelle
4

Ich bin kein Assembly-Experte, aber ich denke, die folgenden Punkte sind nahezu optimal, wenn Sie SIMD-Anweisungen oder Parallelverarbeitung nicht berücksichtigen, die letztere kann leicht erreicht werden, indem Teile des Arrays an die Funktion übergeben werden.

>

wie
Thread1: SubArray (ar1 [0], ar2 [0], 50); Thread2: SubArray (ar1 [50], ar2 [50], 50);

%Vor%     
arthurprs 16.02.2011 00:42
quelle
2

Es ist keine echte Antwort auf Ihre Frage, aber ich würde untersuchen, ob ich die Subtraktion bereits zu einem bestimmten Zeitpunkt durchführen könnte , während die Arrays mit Werten füllt. Ich würde optional sogar ein drittes Array in dem Speicher betrachten, um das Ergebnis der Subtraktion zu speichern. In der modernen Computertechnik sind die "Kosten" des Speichers erheblich niedriger als die "Kosten" der Zeit, die benötigt wird, um eine zusätzliche Speicheraktion auszuführen.

Theoretisch werden Sie zumindest etwas Leistung erzielen, wenn die Subtraktion durchgeführt werden kann, während sich die Werte noch in Registern oder im Prozessor-Cache befinden. In der Praxis stößt man jedoch auf einige Tricks, die die Leistung des gesamten Algorithmus verbessern könnten .

    
Stijn Sanders 16.02.2011 08:10
quelle

Tags und Links