sincos Optimierung in VS2017 15.5 Preview
-
für alle die gerne viele Sin/Cos Kombinationen eines Winkels berechnen
mit dem kommenden 15.5 Update vom V2017 kann der CL das jetzt auch wie der clang/gcc optimieren
https://blogs.msdn.microsoft.com/visualstudio/2017/10/11/visual-studio-2017-version-15-5-preview/
C++ Code Generation:
...the combining of calls sin(x) and cos(x) into a new sincos(x)...bin mal gespannt wie sich das auf die Geschwindigkeit auswirkt und ob das Feature auch deaktiviert werden kann - für einfache vor/nachher Vergleiche
-
-
sin cos werden aber nicht zusammen gefasst
VS2017 Community 15.5.0, x64 Release
oder braucht man dafür die Pro Variante?#include <cmath> struct sincos_struct { sincos_struct(const double value) :_s(sin(value)), _c(cos(value)) {} const double _s; const double _c; }; void sincos_func(const double value, double& s, double& c) { s = sin(value); c = cos(value); } int main() { sincos_struct sc(3.5); double s; double c; sincos_func(3.5, s, c); return 0; }
in beiden Code sind man die getrennten sin/cos Aufrufe
Assembler-Listing:
; Listing generated by Microsoft (R) Optimizing Compiler Version 19.12.25830.2 include listing.inc INCLUDELIB OLDNAMES EXTRN __security_check_cookie:PROC PUBLIC main PUBLIC ?sincos_func@@YAXNAEAN0@Z ; sincos_func PUBLIC ??0sincos_struct@@QEAA@N@Z ; sincos_struct::sincos_struct EXTRN cos:PROC EXTRN sin:PROC EXTRN _fltused:DWORD ; COMDAT pdata pdata SEGMENT $pdata$?sincos_func@@YAXNAEAN0@Z DD imagerel $LN4 DD imagerel $LN4+61 DD imagerel $unwind$?sincos_func@@YAXNAEAN0@Z pdata ENDS ; COMDAT pdata pdata SEGMENT $pdata$??0sincos_struct@@QEAA@N@Z DD imagerel $LN4 DD imagerel $LN4+56 DD imagerel $unwind$??0sincos_struct@@QEAA@N@Z pdata ENDS ; COMDAT xdata xdata SEGMENT $unwind$??0sincos_struct@@QEAA@N@Z DD 040b01H DD 02680bH DD 030025206H xdata ENDS ; COMDAT xdata xdata SEGMENT $unwind$?sincos_func@@YAXNAEAN0@Z DD 060f01H DD 02680fH DD 08340aH DD 07006520aH xdata ENDS ; Function compile flags: /Ogtpy ; File d:\test\sincos\sincos.cpp ; COMDAT ??0sincos_struct@@QEAA@N@Z _TEXT SEGMENT this$ = 64 value$ = 72 ??0sincos_struct@@QEAA@N@Z PROC ; sincos_struct::sincos_struct, COMDAT $LN4: push rbx sub rsp, 48 ; 00000030H movaps XMMWORD PTR [rsp+32], xmm6 movaps xmm0, xmm1 movaps xmm6, xmm1 mov rbx, rcx call sin movsd QWORD PTR [rbx], xmm0 movaps xmm0, xmm6 call cos movaps xmm6, XMMWORD PTR [rsp+32] mov rax, rbx movsd QWORD PTR [rbx+8], xmm0 add rsp, 48 ; 00000030H pop rbx ret 0 ??0sincos_struct@@QEAA@N@Z ENDP ; sincos_struct::sincos_struct _TEXT ENDS ; Function compile flags: /Ogtpy ; File d:\test\sincos\sincos.cpp ; COMDAT ?sincos_func@@YAXNAEAN0@Z _TEXT SEGMENT value$ = 64 s$ = 72 c$ = 80 ?sincos_func@@YAXNAEAN0@Z PROC ; sincos_func, COMDAT $LN4: mov QWORD PTR [rsp+8], rbx push rdi sub rsp, 48 ; 00000030H movaps XMMWORD PTR [rsp+32], xmm6 mov rdi, r8 movaps xmm6, xmm0 mov rbx, rdx call sin movsd QWORD PTR [rbx], xmm0 movaps xmm0, xmm6 call cos mov rbx, QWORD PTR [rsp+64] movaps xmm6, XMMWORD PTR [rsp+32] movsd QWORD PTR [rdi], xmm0 add rsp, 48 ; 00000030H pop rdi ret 0 ?sincos_func@@YAXNAEAN0@Z ENDP ; sincos_func _TEXT ENDS ; Function compile flags: /Ogtpy ; File d:\test\sincos\sincos.cpp ; COMDAT main _TEXT SEGMENT main PROC ; COMDAT xor eax, eax ret 0 main ENDP _TEXT ENDS END
jemand eine Idee - oder eine Pro version zum testen?
-
VS2017 Community 15.5.0 x86 liefert
; Listing generated by Microsoft (R) Optimizing Compiler Version 19.12.25830.2 TITLE d:\test\sincos\sincos.cpp .686P .XMM include listing.inc .model flat INCLUDELIB OLDNAMES EXTRN @__security_check_cookie@4:PROC PUBLIC _main PUBLIC ?sincos_func@@YAXNAAN0@Z ; sincos_func PUBLIC ??0sincos_struct@@QAE@N@Z ; sincos_struct::sincos_struct EXTRN __libm_sse2_cos_precise:PROC EXTRN __libm_sse2_sin_precise:PROC EXTRN __fltused:DWORD ; Function compile flags: /Ogtp ; File d:\test\sincos\sincos.cpp ; COMDAT ??0sincos_struct@@QAE@N@Z _TEXT SEGMENT _value$1$ = -8 ; size = 8 ??0sincos_struct@@QAE@N@Z PROC ; sincos_struct::sincos_struct, COMDAT ; _this$ = ecx ; _value$ = xmm1l push ebp mov ebp, esp sub esp, 12 ; 0000000cH movaps xmm0, xmm1 push esi movsd QWORD PTR _value$1$[ebp], xmm0 mov esi, ecx call __libm_sse2_sin_precise movsd QWORD PTR [esi], xmm0 movsd xmm0, QWORD PTR _value$1$[ebp] call __libm_sse2_cos_precise movsd QWORD PTR [esi+8], xmm0 mov eax, esi pop esi mov esp, ebp pop ebp ret 0 ??0sincos_struct@@QAE@N@Z ENDP ; sincos_struct::sincos_struct _TEXT ENDS ; Function compile flags: /Ogtp ; File d:\testsincos\sincos.cpp ; COMDAT ?sincos_func@@YAXNAAN0@Z _TEXT SEGMENT _value$1$ = -8 ; size = 8 ?sincos_func@@YAXNAAN0@Z PROC ; sincos_func, COMDAT ; _s$ = ecx ; _c$ = edx ; _value$ = xmm2l push ebp mov ebp, esp sub esp, 8 push esi movaps xmm0, xmm2 mov esi, ecx push edi movsd QWORD PTR _value$1$[ebp], xmm0 mov edi, edx call __libm_sse2_sin_precise movsd QWORD PTR [esi], xmm0 movsd xmm0, QWORD PTR _value$1$[ebp] call __libm_sse2_cos_precise movsd QWORD PTR [edi], xmm0 pop edi pop esi mov esp, ebp pop ebp ret 0 ?sincos_func@@YAXNAAN0@Z ENDP ; sincos_func _TEXT ENDS ; Function compile flags: /Ogtp ; File d:\test\sincos\sincos.cpp ; COMDAT _main _TEXT SEGMENT _main PROC ; COMDAT push ebp mov ebp, esp and esp, -8 ; fffffff8H xor eax, eax mov esp, ebp pop ebp ret 0 _main ENDP _TEXT ENDS END
-
main PROC ; COMDAT xor eax, eax ret 0
...
-
@dot - ja die main ist leer - für den generierten struct/function-Code unrelevant, oder was meinst du?
hier etwas wo wirklich gerechnet wird - ich benutze argc und main result nur als Anti-Optimizer Trick, der Eingangswert und das Ergebnis sind völlig sinnfrei
#include <cmath> struct sincos_struct { sincos_struct(const double value) :_s(sin(value)), _c(cos(value)) {} const double _s; const double _c; }; void sincos_func(const double value, double& s, double& c) { s = sin(value); c = cos(value); } int main(int argc, char** argv) { double v = argc; // anti-optimizer double res = 0.0; sincos_struct sc(v); res += sc._s + sc._c; double s; double c; sincos_func(v, s, c); res += s + c; return (int)res; // anti-optimizer }
da ändert sich auch nichts
; Listing generated by Microsoft (R) Optimizing Compiler Version 19.12.25830.2 include listing.inc INCLUDELIB OLDNAMES EXTRN __security_check_cookie:PROC PUBLIC main PUBLIC ?sincos_func@@YAXNAEAN0@Z ; sincos_func PUBLIC ??0sincos_struct@@QEAA@N@Z ; sincos_struct::sincos_struct EXTRN cos:PROC EXTRN sin:PROC EXTRN _fltused:DWORD ; COMDAT pdata pdata SEGMENT $pdata$main DD imagerel $LN8 DD imagerel $LN8+77 DD imagerel $unwind$main pdata ENDS ; COMDAT pdata pdata SEGMENT $pdata$?sincos_func@@YAXNAEAN0@Z DD imagerel $LN4 DD imagerel $LN4+61 DD imagerel $unwind$?sincos_func@@YAXNAEAN0@Z pdata ENDS ; COMDAT pdata pdata SEGMENT $pdata$??0sincos_struct@@QEAA@N@Z DD imagerel $LN4 DD imagerel $LN4+56 DD imagerel $unwind$??0sincos_struct@@QEAA@N@Z pdata ENDS ; COMDAT xdata xdata SEGMENT $unwind$??0sincos_struct@@QEAA@N@Z DD 040b01H DD 02680bH DD 030025206H xdata ENDS ; COMDAT xdata xdata SEGMENT $unwind$?sincos_func@@YAXNAEAN0@Z DD 060f01H DD 02680fH DD 08340aH DD 07006520aH xdata ENDS ; COMDAT xdata xdata SEGMENT $unwind$main DD 051501H DD 027815H DD 036809H DD 08204H xdata ENDS ; Function compile flags: /Ogtpy ; COMDAT ??0sincos_struct@@QEAA@N@Z _TEXT SEGMENT this$ = 64 value$ = 72 ??0sincos_struct@@QEAA@N@Z PROC ; sincos_struct::sincos_struct, COMDAT ; File d:\test\sincos\sincos.cpp ; Line 5 $LN4: push rbx sub rsp, 48 ; 00000030H movaps XMMWORD PTR [rsp+32], xmm6 movaps xmm0, xmm1 movaps xmm6, xmm1 mov rbx, rcx call sin movsd QWORD PTR [rbx], xmm0 movaps xmm0, xmm6 call cos movaps xmm6, XMMWORD PTR [rsp+32] mov rax, rbx movsd QWORD PTR [rbx+8], xmm0 add rsp, 48 ; 00000030H pop rbx ret 0 ??0sincos_struct@@QEAA@N@Z ENDP ; sincos_struct::sincos_struct _TEXT ENDS ; Function compile flags: /Ogtpy ; COMDAT ?sincos_func@@YAXNAEAN0@Z _TEXT SEGMENT value$ = 64 s$ = 72 c$ = 80 ?sincos_func@@YAXNAEAN0@Z PROC ; sincos_func, COMDAT ; File d:\testsincos\sincos.cpp ; Line 11 $LN4: mov QWORD PTR [rsp+8], rbx push rdi sub rsp, 48 ; 00000030H movaps XMMWORD PTR [rsp+32], xmm6 mov rdi, r8 movaps xmm6, xmm0 mov rbx, rdx ; Line 12 call sin movsd QWORD PTR [rbx], xmm0 ; Line 13 movaps xmm0, xmm6 call cos ; Line 14 mov rbx, QWORD PTR [rsp+64] movaps xmm6, XMMWORD PTR [rsp+32] movsd QWORD PTR [rdi], xmm0 add rsp, 48 ; 00000030H pop rdi ret 0 ?sincos_func@@YAXNAEAN0@Z ENDP ; sincos_func _TEXT ENDS ; Function compile flags: /Ogtpy ; COMDAT main _TEXT SEGMENT argc$ = 80 argv$ = 88 main PROC ; COMDAT ; File d:\test\sincos\sincos.cpp ; Line 17 $LN8: sub rsp, 72 ; 00000048H movaps XMMWORD PTR [rsp+48], xmm6 xorps xmm6, xmm6 ; Line 18 cvtsi2sd xmm6, ecx movaps XMMWORD PTR [rsp+32], xmm7 ; Line 5 movaps xmm0, xmm6 call sin movaps xmm7, xmm0 movaps xmm0, xmm6 call cos ; Line 31 movaps xmm6, XMMWORD PTR [rsp+48] addsd xmm7, xmm0 xorps xmm1, xmm1 movaps xmm2, xmm7 addsd xmm2, xmm1 addsd xmm2, xmm7 movaps xmm7, XMMWORD PTR [rsp+32] cvttsd2si eax, xmm2 add rsp, 72 ; 00000048H ret 0 main ENDP _TEXT ENDS END
-
scheinbar nur mit /fp:fast aktiv
beim clang muss man -ffast-math nutzen um die sincos Optimierung zu bekommen, der gcc macht sincos per default
-
hier noch ein Blog mit Details zu den Verbesserungen
MSVC code optimizer improvements in Visual Studio 2017 versions 15.5 and 15.3