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