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++;
}

コンパイラーにこの操作をベクトル化してもらいたいのですが、そうではありません。最適化を有効にする必要があると思います。

私は 2 つのソリューションを手作業でコーディングしました。1 つはインライン__asmブロックを使用し、もう 1 つは で定義された SSE2 組み込み関数を使用し<emmintrin.h>ます。これに頼らない方がいいです。

アップデート

memcpy上記の質問に加えて、必要に応じて提供されたベクトル化されたバージョンを使用するために、ライブラリ関数の呼び出しを希望します。のアセンブリ コードを見ると、 コピーを高速化するために を使用するmemcpy関数が呼び出されていることがわかります。このルーチンに分岐するかどうかを決定するブロックは次のとおりです。_VEC_memcpySSE2

    ; 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、コンパイラが浮動小数点演算に x87 FPU の代わりにスカラー SSE を使用できるようにすることです。

したがって、x64 でより多くのレジスタにアクセスできるため、速度が向上する可能性があります。/arch:SSE2ただし、ベクトル化によるものではないことに注意してください。

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 のデバッグ設定を使用してビルドされたコードを最適化しようとするのは、一種のばかげた用事です。コンパイラは、たとえばデータをスタックに出し入れするなどして、コードを遅くしようとしているからです (これにより、load-hit-store のストールが発生します)。などなど。

いずれにせよ、MSVC はリリースでもデバッグでも、そのブロックをベクトル化しません。適切なマシン コードを出力するには、組み込み関数を使用する必要があります。これは /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 に答える