2011-11-03 16 views
11

Làm cách nào để kiểm tra xem biến số __m128i có bất kỳ giá trị không đồng bộ nào trên bộ xử lý SSE-2 và cũ hơn không?Biến số __m128i có bằng không?

+0

Bạn có nghĩa là một bit khác không hoặc một phần tử số nguyên 8/16/32-bit? –

+0

@BrettHale: Tôi đang thử nghiệm để xem liệu chúng có bằng không. – Mehrdad

Trả lời

11

Trong SSE2 bạn có thể làm:

__m128i zero = _mm_setzero_si128(); 
if(_mm_movemask_epi8(_mm_cmpeq_epi32(x,zero)) == 0xFFFF) 
{ 
    //the code... 
} 

này sẽ kiểm tra Bốn int của vs zero sau đó trả về một mặt nạ cho từng byte, vì vậy bit offsets lại mỗi cái tương ứng int sẽ là 0, 4, 8 & 12, nhưng các thử nghiệm trên sẽ bắt nếu bất kỳ bit được thiết lập, sau đó nếu bạn bảo vệ mặt nạ bạn có thể làm việc với các phần hạt mịn hơn trực tiếp nếu cần thiết.

+2

+1, nó tốt hơn tôi. :) Tôi chưa bao giờ sử dụng lệnh movemask vì vậy tôi không biết bạn có thể làm điều đó. XD – Mysticial

+0

+1 giải pháp nhỏ gọn nhất mà tôi từng thấy, cảm ơn! – Mehrdad

+3

Có một lỗi trong câu trả lời tuyệt vời khác - nếu bạn đang kiểm tra tất cả các số không, nó phải là 'if (_mm_movemask_epi8 (_mm_cmpeq_epi32 (x, zero)) == 0xFFFF)'. Điều này là do '_mm_cmpeq_epi32' đặt int thành tất cả 1, không phải tất cả 0, nếu nó bằng 0, và sau đó' _mm_movemask_epi8' đặt 16 bit đầu tiên dựa trên bit quan trọng nhất của mỗi byte trong đối số. Hy vọng rằng tác giả có thể chỉnh sửa câu trả lời - tôi đã thử nhưng đã bị từ chối. – FarmerBob

1

Vì mục đích hoàn chỉnh, với SSE4 người ta có thể sử dụng _mm_testz_si128.

const bool isAllZero = _mm_testz_si128(a,a); 

Lưu ý rằng đây là đúng khi tất cả các bit là zero.

+1

Điều này thực sự nhanh hơn một chút và không cần đăng ký tất cả 0 để kiểm tra. 'ptest' /' jz' là 2 + 1 uop (không macro-fuse). 'pcmpeq' (1uop) /' pmovmsk' (1uop)/'và 0xffff' (1uop) /' cmp 0xffff/je' (1uop). Nếu bạn đang thử nghiệm trường hợp khác (* bất kỳ * phần tử không, thay vì * tất cả * phần tử không), chúng sẽ xấp xỉ hiệu suất tương tự trên các CPU Intel và AMD hiện tại: 'ptest' /' jnz' (3 uops) vs 'pcmpeq' /' pmovmsk'/'test/jnz' (3 uops). –

+0

@PeterCordes Thế còn, trong trường hợp đó, có một bộ đăng ký ở tất cả, và sử dụng '_mm_testc_si128'? Một cái gì đó như 'const bool atLeastOneZero = _mm_testc_si128 (a, allOnes)' – Antonio

+1

Một lần nữa, 'ptest' hơi nhanh hơn. Để làm điều đó mà không có 'ptest', bạn sẽ' pcmpeq' so với tất cả các vector, và sau đó tiến hành chính xác cùng một chuỗi để kiểm tra xem tất cả các phần tử có khớp nhau hay không. Việc kiểm tra tất cả 0 hoặc tất cả-một với 'pcmpeq' giống như kiểm tra == đối với bất kỳ mẫu nào khác, ngoại trừ các hằng số dễ tạo ra hơn khi đang bay (' pxor same, same' hoặc 'pcmpeqw same, cùng '). –

Các vấn đề liên quan