2011-05-26 17 views
6

Eşitlik için chunk-wise iki arabelleği karşılaştırmalıyım. İki arabelleğin her ikisi de eşitse veya olmasın, iki arabelleğin ilişkisi hakkında bilgiye ihtiyacım yok. Hiç SSE kullanarak benim ilk denemede için, arabellekleri olabildiğince hızlı bir şekilde karşılaştırır.

const size_t CHUNK_SIZE = 16; //128bit for SSE2 integer registers 
const int ARRAY_SIZE = 200000000; 

char* array_1 = (char*)_aligned_malloc(ARRAY_SIZE, 16); 
char* array_2 = (char*)_aligned_malloc(ARRAY_SIZE, 16); 

for (size_t i = 0; i < ARRAY_SIZE;) 
{ 
    volatile bool result = memcmp(array_1+i, array_2+i, CHUNK_SIZE); 
    i += CHUNK_SIZE; 
} 

karşılaştırıldığında: My istihbarat makinesi

naif bir yaklaşımdır SSE4.2 destekler hız

union U 
{ 
    __m128i m; 
    volatile int i[4]; 
} res; 

for (size_t i = 0; i < ARRAY_SIZE;) 
{ 
    __m128i* pa1 = (__m128i*)(array_1+i); 
    __m128i* pa2 = (__m128i*)(array_2+i); 
    res.m = _mm_cmpeq_epi32(*pa1, *pa2); 
    volatile bool result = ((res.i[0]==0) || (res.i[1]==0) || (res.i[2]==0) || (res.i[3]==0)); 
    i += CHUNK_SIZE; 
} 

kazanç yaklaşık 33% 'dir. Daha iyisini yapabilir miyim?

+0

Bu kodda bir darboğaz var mı? –

+0

Evet, programımın en önemli noktası. – beutelfuchs

+0

'Memcmpy 'uygulamanız bozulmazsa, onu zorlamakta zorlanacaksınız - zaten SIMD tarafından optimize edilmiş olmalıdır. –

cevap

4

Gerçekten tüm bireysel vektör öğeleri test etmek skaler kodu ve sendikaları kullanarak olmamalı - artık şöyle bir şey yapmak: Eğer SSE 4.1 kullanabilirsiniz yana

for (size_t i = 0; i < ARRAY_SIZE; i += CHUNK_SIZE) 
{ 
    const __m128i a1 = _mm_load_si128(array_1 + i); 
    const __m128i a2 = _mm_load_si128(array_2 + i); 
    const __m128i vcmp = _mm_cmpeq_epi32(a1, a2); 
    const int vmask = _mm_movemask_epi8(vcmp); 
    const bool result = (vmask == 0xffff); 
    // you probably want to break here if you get a mismatch ??? 
} 
+0

teşekkür ederiz VS2005 çıkışı daha benim makinede yavaştır, ben – beutelfuchs

+0

Ama arıyorum bilgiler maalesef kazanç kullanarak kıyasla aynı ise tam türüdür Bu özel durum için sendika. – beutelfuchs

+0

Bu sizin darboğazınızın bellek bant genişliği olması olabilir, bu yüzden karşılaştırma işlemlerini hızlandırmak sonuçsuz olabilir. –

2

, olabilecek başka bir alternatif var daha hızlı:

for (size_t i = 0; i < ARRAY_SIZE; i += CHUNK_SIZE;) 
{ 
    __m128i* pa1 = (__m128i*)(array_1+i); 
    __m128i* pa2 = (__m128i*)(array_2+i); 
    __m128i temp = _mm_xor_si128(*pa1, *pa2); 
    bool result = (bool)_mm_testz_si128(temp, temp); 
} 

_mm_testz_si128(a, b) döner 0a & b != 0 eğer ve 1a & b == 0 eğer döner. Bunun avantajı, bu sürümü yepyeni AVX komutlarıyla birlikte kullanabilmenizdir, ayrıca yığın boyutu 32 bayttır.

+0

Teşekkür ederiz. Maalesef VS2005 o anda öğrendiğim gibi v2'nin üzerindeki SSE'yi desteklemiyor. Belki de opcodes'u bulabilir ve bunun yerine inline asm kullanabilirim. – beutelfuchs

+0

Bu yönergeleri destekleyen intel compiler'ı kullanmayı denedim.Performans, burada sunulan diğer yaklaşımlarla karşılaştırılabilir. – beutelfuchs

+0

Kodu denediğiniz için teşekkürler. Paul R tarafından belirtildiği gibi, bellek bant genişliğinin buradaki darboğaz olması oldukça olasıdır. Bu kod potansiyel olarak 1 veya 2 çevrim daha hızlı olabilir. –

İlgili konular