質問

Can the compiler make automatic use of SSE2 while optimisations are disabled?

When optimisations are disabled, does the /arch:SSE2 flag mean anything?

I've been given the task of squeezing more performance out of our software. Unfortunately, release builds are done using the debug settings, and attempts to argue for the case of optimisation have been unsuccessful so far.

Compiling for x86 with compiler flags /ZI /Od /arch:SSE2 /FAs. The generated assembly shows that the compiler is not making use of SSE2. Is this because optimisation is disabled?

In the code, there are a few situations similar to this:

char* begin = &bufferObject;
char* end   = begin + sizeof(bufferObject);
char  result;
while ( begin != end ) {
    result ^= *begin++;
}

I'd like to have the compiler vectorise this operation for me, but it doesn't; I suspect optimisation needs to be enabled.

I hand-coded two solutions: one using an inline __asm block, and the other using the SSE2 intrinsicts defined in <emmintrin.h>. I'd prefer not to rely on this.

Update

Further to the questions above, I would like calls to library functions, like memcpy, to use the provided vectorised versions when appropriate. Looking at the assembly code for memcpy, I can see that there is a function called _VEC_memcpy which makes use of SSE2 for faster copying. The block which decides whether to branch to this routine or not is this:

    ; First, see if we can use a "fast" copy SSE2 routine
    ; block size greater than min threshold?
    cmp     ecx,080h
    jb      Dword_align
    ; SSE2 supported?
    cmp     DWORD PTR __sse2_available,0
    je      Dword_align
    ; alignments equal?
    push    edi
    push    esi
    and     edi,15
    and     esi,15
    cmp     edi,esi
    pop     esi
    pop     edi
    jne     Dword_align

    ; do fast SSE2 copy, params already set
    jmp     _VEC_memcpy

I don't think that _VEC_memcpy is being called... ever.

Should the /arch:SSE2 flag be defining this __sse2_available symbol?

役に立ちましたか?

解決

Visual Studio 2010 and earlier has no support for automatic vectorization at all.

The purpose of /arch:SSE2 is to allow the compiler to use scalar SSE for floating-point operations instead of the x87 FPU.

So you may get some speedup with /arch:SSE2 since it allows you to access more registers on x64. But keep it mind that it is not from vectorization.

If you want vectorization on VS2010, you pretty much have to do it manually with intrinsics.


Visual Studio 2012 has support for auto-vectorization:

http://msdn.microsoft.com/en-us/library/hh872235%28v=vs.110%29.aspx

他のヒント

Trying to optimize code built with MSVC's debug settings is kind of a fool's errand, since the compiler is effectively going out of its way to make your code slow by eg juggling data onto and off the stack (which induces load-hit-store stalls) and other such things.

In any case, MSVC doesn't vectorize that block whether in Release or Debug. You'll need to use intrinsics to get it to emit the right machine code. This is /O2 /Ot /Oi /arch:SSE2 :

PUBLIC  ?VectorTest@@YADPAD0@Z              ; VectorTest
; Function compile flags: /Ogtp
;   COMDAT ?VectorTest@@YADPAD0@Z
_TEXT   SEGMENT
_begin$ = 8                     ; size = 4
_result$ = 11                       ; size = 1
_end$ = 12                      ; size = 4
?VectorTest@@YADPAD0@Z PROC             ; VectorTest, COMDAT

; 143  : {

    push    ebp
    mov ebp, esp

; 144  :    char  result;
; 145  :    while ( begin != end ) {

    mov ecx, DWORD PTR _begin$[ebp]
    mov edx, DWORD PTR _end$[ebp]
    mov al, BYTE PTR _result$[ebp]
    cmp ecx, edx
    je  SHORT $LN1@VectorTest
$LL2@VectorTest:

; 146  :        result ^= *begin++;

    xor al, BYTE PTR [ecx]
    inc ecx
    cmp ecx, edx
    jne SHORT $LL2@VectorTest
$LN1@VectorTest:

; 147  :    }
; 148  :    return result;
; 149  : }

    pop ebp
    ret 0
?VectorTest@@YADPAD0@Z ENDP             ; VectorTest
_TEXT   ENDS

Contemporary compilers are really lousy at vectorization, so we rely on using SSE intrinsics throughout our app. I doubt any compiler would vectorize that particular operation as it is essentially a "reduce" rather than a "map", and I've yet to see a compiler that does horizontal (non-orthogonal) vectorization.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top