2013-03-06 4 views
5

Ich habe Code, der eine Menge_ftol2_sse, gibt es schnellere Optionen?

int myNumber = (int)(floatNumber); 

nennt, die insgesamt rund 10% meiner CPU-Zeit (nach Profiler) in Anspruch nimmt. Während ich es dabei belassen könnte, frage ich mich, wenn es schnelle Optionen sind, so habe ich versucht, die Suche um und stolperte über

http://devmaster.net/forums/topic/7804-fast-int-float-conversion-routines/ http://stereopsis.com/FPU.html

Ich versuchte, die Real2Int() Funktion implementiert dort gegeben , aber es gibt mir falsche Ergebnisse und läuft langsamer. Nun, ich frage mich, gibt es schnellere Implementierungen, um Double/Float-Werte auf Ganzzahlen zu setzen, oder ist die SSE2-Version so schnell wie es geht? Die Seiten, die ich gefunden habe, stammen ein wenig zurück, also könnte es einfach veraltet sein, und neuere STL sind schneller.

Die aktuelle Implementierung tut:

013B1030 call  _ftol2_sse (13B19A0h) 

013B19A0 cmp   dword ptr [___sse2_available (13B3378h)],0 
013B19A7 je   _ftol2 (13B19D6h) 
013B19A9 push  ebp 
013B19AA mov   ebp,esp 
013B19AC sub   esp,8 
013B19AF and   esp,0FFFFFFF8h 
013B19B2 fstp  qword ptr [esp] 
013B19B5 cvttsd2si eax,mmword ptr [esp] 
013B19BA leave 
013B19BB ret 

Verwandte Fragen, die ich gefunden:

Fast float to int conversion and floating point precision on ARM (iPhone 3GS/4)

What is the fastest way to convert float to int on x86

beide Da sind alt, oder sind ARM-basierte, I frage mich, ob es da ist aktuelle Möglichkeiten, dies zu tun. Beachten Sie, dass es besagt, dass die beste Konvertierung eine ist, die nicht passiert, aber ich muss sie haben, damit das nicht möglich ist.

Antwort

6

Es wird schwer zu schlagen, wenn Sie auf generische x86-Hardware abzielen. Die Laufzeitumgebung kann nicht sicher sein, dass der Zielcomputer über eine SSE-Einheit verfügt. Wenn dies der Fall ist, könnte es tun, was der x64-Compiler tut und einen cvttss2si Opcode inline. Da die Runtime jedoch prüfen muss, ob eine SSE-Einheit verfügbar ist, bleibt die aktuelle Implementierung übrig. Das macht die Implementierung von ftol2_sse. Und außerdem übergibt es den Wert in einem x87-Register und überträgt es dann in ein SSE-Register, wenn eine SSE-Einheit verfügbar ist.

Sie könnten den x86-Compiler an Zielcomputer mit SSE-Einheiten verweisen. Dann würde der Compiler tatsächlich einen einfachen cvttss2si Opcode inline ausgeben. Das wird so schnell wie möglich. Aber wenn Sie den Code auf einem älteren Computer ausführen, wird es fehlschlagen. Vielleicht könnten Sie zwei Versionen liefern, eine für Maschinen mit SSE, und eine für solche ohne.

Das wird dich nicht allzu sehr gewinnen. Es wird nur den Overhead von ftol2_sse vermeiden, der passiert, bevor Sie tatsächlich den cvttss2si Opcode erreichen, der die Arbeit erledigt.

Um die Compilereinstellungen von der IDE zu ändern, verwenden Sie Projekt> Eigenschaften> Konfigurationseigenschaften> C/C++> Codegenerierung> Erweiterten Befehlssatz aktivieren. In der Befehlszeile ist/arch: SSE oder/arch: SSE2.

+0

perfekt, mit x64-Code funktioniert das viel schneller! – SinisterMJ

1

Für double Ich glaube nicht, Sie in der Lage sein wird, die Ergebnisse viel zu verbessern, aber wenn Sie eine Menge float s zu konvertieren, dass eine gepackte Umwandlung verwendet, könnte helfen, die folgende ist nasm Code:

global _start 

section .data 
    align 16 
    fv1: dd 1.1, 2.5, 2.51, 3.6 

section .text 
    _start: 

    cvtps2dq xmm1, [fv1] ; Convert four 32-bit(single precision) floats to 32-bit(double word) integers and place the result in xmm1 

Es sollte intrinsics Code geben, der Ihnen erlaubt, das gleiche auf eine einfachere Weise zu machen, aber ich bin nicht so vertraut mit der Verwendung von intrinsischen Bibliotheken. Obwohl Sie nicht gcc verwenden, ist dieser Artikel Auto-vectorization with gcc 4.7 ein Augenöffner auf, wie schwer es sein kann, den Compiler zu erhalten, guten vektorisierten Code zu generieren.

1

Wenn Sie Geschwindigkeit und eine große Basis an Zielmaschinen benötigen, sollten Sie eine schnelle SSE-Version aller Ihrer Algorithmen sowie eine allgemeine - und wählen Sie die Algorithmen, die auf einer viel höheren Ebene ausgeführt werden.

Dies würde auch bedeuten, dass auch der ABI für SSE optimiert ist; und dass Sie die Berechnung, wenn verfügbar, vektorisieren können und dass auch die Steuerlogik für die Architektur optimiert ist.

btw. sogar FLD; FIST Sequenz sollte nicht länger als ~ 7 Taktzyklen auf Pentium dauern.

+3

Sie müssen den Rundungsmodus ändern, um die korrekte Kürzung zu erhalten. Das Ändern des x87 Statuswortes ist langsam, soweit ich weiß. –

+0

@ infats Kommentar ist genau –

+0

Guter Punkt. Es wäre dann sinnvoll, das Statuswort _oft_ nicht zu ändern. –

Verwandte Themen