4

禁用优化时编译器能否自动使用 SSE2?

当优化被禁用时,/arch:SSE2 标志是否意味着什么?

我的任务是从我们的软件中榨取更多性能。不幸的是,发布构建是使用调试设置完成的,到目前为止,为优化案例争论的尝试都没有成功。

使用编译器标志为 x86 编译/ZI /Od /arch:SSE2 /FAs。生成的程序集表明编译器没有使用SSE2. 这是因为优化被禁用了吗?

在代码中,有几种类似的情况:

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

我想让编译器为我向量化这个操作,但它没有;我怀疑需要启用优化。

我手工编写了两种解决方案:一种使用内联__asm块,另一种使用<emmintrin.h>. 我宁愿不依赖这个。

更新

除上述问题外,我希望调用库函数,例如memcpy,在适当的时候使用提供的矢量化版本。查看 的汇编代码memcpy,我可以看到有一个调用的函数_VEC_memcpy用于SSE2 更快地复制。决定是否分支到此例程的块是:

    ; 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

我不认为这_VEC_memcpy被称为......永远

标志应该/arch:SSE2定义这个__sse2_available符号吗?

4

2 回答 2

9

Visual Studio 2010 及更早版本根本不支持自动矢量化。

的目的/arch:SSE2是允许编译器使用标量 SSE 进行浮点运算,而不是 x87 FPU。

因此,您可能会获得一些加速,/arch:SSE2因为它允许您访问 x64 上的更多寄存器。但请记住,它不是来自矢量化。

如果你想在 VS2010 上进行矢量化,你几乎必须用内在函数手动完成。


Visual Studio 2012 支持自动矢量化:

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

于 2012-07-11T00:57:54.857 回答
4

尝试优化使用 MSVC 的调试设置构建的代码是一种愚蠢的差事,因为编译器通过例如将数据进出堆栈(这会导致加载命中存储停顿)来有效地使您的代码变慢和其他类似的事情。

在任何情况下,MSVC 都不会在 Release 或 Debug 中对该块进行矢量化。您需要使用内在函数来让它发出正确的机器代码。这是 /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

现代编译器在矢量化方面真的很糟糕,所以我们依赖于在整个应用程序中使用 SSE 内在函数。我怀疑任何编译器都会向量化该特定操作,因为它本质上是“减少”而不是“映射”,而且我还没有看到执行水平(非正交)向量化的编译器。

于 2012-07-11T01:07:12.553 回答