2014-07-18 20 views
7

Bu soru, gcc (4.6.3 Ubuntu) ve SSE intrinsics için açılma döngülerindeki davranışı ile hemen işlenenlerle ilgilidir.Ne gcc seçeneği, SSE intrinsics için anında işlenenlerle döngü açmayı sağlar?

Anında işlenen bir içsel örnek, _mm_blend_ps'dir. Yalnızca sabit olabilen 4 bitlik bir tamsayıyı bekler. Bununla birlikte, -O3 seçeneğini kullanarak, derleyici görünür şekilde döngüleri otomatik olarak açar (döngü sayacı değerleri derleme zamanında belirlenebilirse) ve farklı anlık değerlerle karşılık gelen karışım komutunun birden çok örneğini üretir.

Bu harmanın hemen işlenen 16 olası değerler arasında çalışan basit bir test kodu (blendsimple.c) aşağıdaki gibidir: mümkündür

#include <stdio.h> 
#include <x86intrin.h> 

#define PRINT(V)    \ 
    printf("%s: ", #V);    \ 
    for (i = 3; i >= 0; i--) printf("%3g ", V[i]); \ 
    printf("\n"); 

int 
main() 
{ 
    __m128 a = _mm_set_ps(1, 2, 3, 4); 
    __m128 b = _mm_set_ps(5, 6, 7, 8); 
    int i; 
    PRINT(a); 
    PRINT(b); 
    unsigned mask; 
    __m128 r; 
    for (mask = 0; mask < 16; mask++) { 
    r = _mm_blend_ps(a, b, mask); 
    PRINT(r); 
    } 
    return 0; 
} 

bu kod derleme

gcc -Wall -march=native -O3 -o blendsimple blendsimple.c 

ve kod çalışır. Açıkçası, derleyici döngüyü kaydırarak hemen işlenen için sabitler ekler.

Ancak,

gcc -Wall -march=native -O2 -o blendsimple blendsimple.c 
Eğer içsel harmanı için aşağıdaki hatayı alıyorum

ile kod derleme ise:

error: the last argument must be a 4-bit immediate 

Şimdi belirli derleyici bayrağı aktif olduğunu öğrenmek için çalıştı - O3 ancak -O2'de olmayan, derleyicinin döngüyü açmasına izin vermedi, ancak başarısız oldu.

gcc -c -Q -O3 --help=optimizers > /tmp/O3-opts 
gcc -c -Q -O2 --help=optimizers > /tmp/O2-opts 
diff /tmp/O2-opts /tmp/O3-opts | grep enabled 

-o2 tarafından -o3 değil tarafından etkinleştirilen tüm seçenekleri listelenmektedir:

https://gcc.gnu.org/onlinedocs/gcc-4.8.2/gcc/Overall-Options.html

gcc çevrimiçi dokümanlardan ardından aşağıdaki komutları yürütür. Ben

gcc -Wall -march=native -O2 -fgcse-after-reload -finline-functions -fipa-cp-clone -fpredictive-commoning -ftree-loop-distribute-patterns -ftree-vectorize -funswitch-loops blendsimple blendsimple.c 

-o2 ek olarak 7 sıralanan bayrakların tüm eklediğinizde ı davranış tam -o3 ile aynı olduğunu beklenebilir. Ancak derleyici, "son argümanın derhal 4-bit olması gerektiği" konusunda şikayet ediyor.

Sorunun ne olduğu hakkında bir fikri olan var mı? Bu döngü döngüsünü etkinleştirmek için hangi bayrağın gerekli olduğunu bilmek iyi olur. Bu sayede #pragma GCC optimizasyonu veya bir işlev özelliği kullanılarak seçici olarak etkinleştirilebilir.

(Ayrıca, -O3'ün açma-döngüler seçeneğinin bile etkin olmadığını bile bilmiyorum).

Herhangi bir yardım için minnettar olurum. Bu, verdiğim SSE programlama üzerine bir konferans.

Düzenleme: Yorumlarınız için çok teşekkürler. jtaylor haklı görünüyor. Elimi iki yeni gcc (4.7.3, 4.8.2) sürümüne aldım ve 4.8.2 optimizasyon seviyesinden bağımsız olarak derhal problemden şikayet ediyor. Moverover, daha sonra gcc 4.6.3 kodu -O2 -funroll-döngülerle derlediğini fark ettim, fakat bu da 4.8.2'de başarısız oluyor. Görünüşe göre, bu özelliğe güvenilemez ve Jason R'nin belirttiği gibi, cpp veya şablonlar kullanılarak her zaman "manuel" olarak açılmalıdır.

+0

4-bit bile -o3 ile immediate' . –

+0

Açılış işlemini her zaman önişlemci hilesi veya şablon meta programlaması (C++ ile yazıyorsanız) kullanarak elle uygulayabilirsiniz. –

+1

Bu davranış derleyici hataları (4.8'de giderilmiştir) gibi görünüyor. Derleyicilerin farklı optimizasyon düzeylerinde hatalar vermemesi gerekiyor. gcc, her zaman anlık olmayanları (örneğin şartlı olarak) desteklemeli veya asla desteklememelidir. Daha sonraki sürümlerinde daha sonra seçtikleri görünüyor. Hangi mantıklı, içsel makine talimatları etrafında çok ince sarmalayıcılar olması gerekiyordu – jtaylor

cevap

1

Durumunuz için geçerli olup olmadığından emin değilim, çünkü SSE intrinsics'le aşina değilim.Ama genel olarak, özel olarak sahip kod bölümüne optimize etmek derleyici söyleyebilir:

#pragma GCC push_options 
#pragma GCC optimize ("unroll-loops") 

do your stuff 

#pragma GCC pop_options 

Kaynak: hatası `son argüman olmalıdır olsun Tell gcc to specifically unroll a loop