short als Übergabeparamter gleich schnell wie int?
-
Pikkolini schrieb:
habe, wird dann von modernen Compilern (MSVC, GCC) das ganze zu einem 32-Bit Typ optimiert, oder werden dann zwei mal 16-Bit durch die Register gejagt?
Da hilft wohl nur ausprobieren und im Maschinencode gucken. Sofern du aber auf Geschwindigkeit optimierst, würde ich jedoch auf zwei Maschinenworte tippen. Schließlich würde das Verpacken von zwei Shorts in einen einzelnen, größeren Typ eine nicht trivial Rechenoperation sein für die die Werte ohnehin in den Prozessor geladen werden müssten.
-
Das sagt die Disassembly bei vollständiger Optimierung:
#include <iostream> void foo(int x, int y) { std::cout << x << y << std::endl; } void foo(short x, short y) { std::cout << x << y << std::endl; } int main() { foo(10,10); 013E1000 mov eax,dword ptr [__imp_std::endl (13E2050h)] 013E1005 mov ecx,dword ptr [__imp_std::cout (13E204Ch)] 013E100B push eax 013E100C push 0Ah 013E100E push 0Ah 013E1010 call dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (13E2048h)] 013E1016 mov ecx,eax 013E1018 call dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (13E2048h)] 013E101E mov ecx,eax 013E1020 call dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (13E2044h)] foo(10,10); 013E1026 mov ecx,dword ptr [__imp_std::endl (13E2050h)] 013E102C push ecx 013E102D mov ecx,dword ptr [__imp_std::cout (13E204Ch)] 013E1033 push 0Ah 013E1035 push 0Ah 013E1037 call dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (13E2048h)] 013E103D mov ecx,eax 013E103F call dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (13E2048h)] 013E1045 mov ecx,eax 013E1047 call dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (13E2044h)] return 0; 013E104D xor eax,eax } 013E104F retIch bin jetzt nicht sonderlich Assemblerversiert, aber es sieht so aus, als wäre die Version mit int schneller.
-
mit welchem Program schaut man sich sowas (unter linux) an?
-
padreigh schrieb:
mit welchem Program schaut man sich sowas (unter linux) an?
less

Das ist einfach die Ausgabe wenn du den Compiler mit der -S Option aufrufst.Mach dich auch mit den anderen Zwischenschritten vertraut:
-E: Nur Präprozessor aufrufen, nicht compilieren
-S: Nur Präprozessor und Compiler aufrufen, nicht Assemblieren
-c: Nur Präprozessor, Compiler und Assembler aufrufen, nicht linkenDas alles natürlich nur für GNU Compiler, aber bei anderen Compilern heißen die Optionen meistens genauso. Will ich aber nicht für alle Compiler beschwören.
-
@Pikkolini: Du erstellt zwei gleichnamige Funktionen um einen Unterschied zwischen beiden zu erkennen? Wie wäre es mit foo1 und foo2?
-
@Pikkolini:
Genau Registerbreite oder kleiner als Registerbreite spielt in den meisten Fällen keinen Walzer. Unterschiede können bestehen, sind aber eher zu vernachlässigen.
Wichtig ist halt: nicht GRÖSSER als die Registerbreite. Also 64 bittiges Gedöns mit 32 bittigem Instruction-Set, das tut weh. Merkbar.
-
short sollte 8 Bit sein, also wäre
push 0Ah pop aleigentlich angebracht, aber das wird wohl gar nicht mehr von irgendwelchen compilern unterstützt/umgesetzt.

-
GCC unter x86-64 behandelt short-Werte bei der Übergabe als 32-Bit-Parameter, sprich die höheren 16 Bits werden bei Bedarf durch sign extend ausgelöscht.
Trotzdem werden keine zwei shorts in das gleiche 64-Bit-Register gepackt. Das wäre kontraproduktiv und verbietet sich schon wegen der calling convention.
short-Arithmetik findet dementsprechend hauptsächlich auch auf 32-Bit-Ebene statt, es sei denn, es müssen Werte aus dem RAM gelesen werden.
Ob man short oder int verwendet, ist im Hinblick auf Performanz daher i.d.R. egal, der Compiler macht zum Glück sowieso, was er will.
-
Übersehe ich gerade etwas, oder rufst du einfach zweimal die gleiche Funktion auf?
-
@EinEtwasAndererGast:
Sehe ich auch so.
Ich hab's mal explizit gemacht. Bei mir (VS2005) ist auch keinerlei Unterschied:void fooint(int x, int y) { std::cout << x << y /*<< std::endl*/; } void fooshort(short x, short y) { std::cout << x << y /*<< std::endl*/; } int main() { fooint(10,10); 00401000 mov ecx,dword ptr [__imp_std::cout (402040h)] 00401006 push 0Ah 00401008 push 0Ah 0040100A call dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (402038h)] 00401010 mov ecx,eax 00401012 call dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (402038h)] fooshort(10,10); 00401018 mov ecx,dword ptr [__imp_std::cout (402040h)] 0040101E push 0Ah 00401020 push 0Ah 00401022 call dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (40203Ch)] 00401028 mov ecx,eax 0040102A call dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (40203Ch)] return 0; 00401030 xor eax,eax } 00401032 ret