2012-03-19 26 views
12

Tôi có một véc-tơ đóng gói gồm bốn giá trị dấu phẩy động 64 bit.
Tôi muốn lấy tổng các phần tử của vectơ.Cách nhanh nhất để thực hiện tổng số vectơ ngang với các chỉ dẫn AVX

Với SSE (và sử dụng phao nổi 32-bit) Tôi chỉ có thể làm như sau:

v_sum = _mm_hadd_ps(v_sum, v_sum); 
v_sum = _mm_hadd_ps(v_sum, v_sum); 

Thật không may, mặc dù AVX có hướng dẫn _mm256_hadd_pd, nó khác ở chỗ là kết quả từ các phiên bản SSE. Tôi tin rằng điều này là do thực tế là hầu hết các hướng dẫn AVX hoạt động như các chỉ lệnh SSE cho từng bit 128 bit thấp và riêng biệt, không bao giờ vượt qua ranh giới 128 bit.

Lý tưởng nhất, giải pháp tôi đang tìm kiếm phải tuân thủ các nguyên tắc sau:
1) chỉ sử dụng hướng dẫn AVX/AVX2. (không có SSE)
2) thực hiện không quá 2-3 hướng dẫn.

Tuy nhiên, bất kỳ cách hiệu quả/thanh lịch nào để thực hiện (thậm chí không tuân theo các nguyên tắc trên) luôn được chấp nhận.

Cảm ơn bạn rất nhiều vì đã giúp đỡ.

-Luigi Castelli

+0

Bắt đầu với '_mm256_extractf128_ps',' _mm_add_ps' hai nửa lại với nhau, sau đó sử dụng [các phương pháp hiện có để giảm một vector 128B] (http://stackoverflow.com/questions/6996764/fastest-way-to -do-horizontal-float-vector-sum-on-x86). –

Trả lời

17

Nếu bạn có hai __m256d vectơ x1x2 rằng mỗi chứa bốn double s mà bạn muốn theo chiều ngang Tóm lại, bạn có thể làm:

__m256d x1, x2; 
// calculate 4 two-element horizontal sums: 
// lower 64 bits contain x1[0] + x1[1] 
// next 64 bits contain x2[0] + x2[1] 
// next 64 bits contain x1[2] + x1[3] 
// next 64 bits contain x2[2] + x2[3] 
__m256d sum = _mm256_hadd_pd(x1, x2); 
// extract upper 128 bits of result 
__m128d sum_high = _mm256_extractf128_pd(sum1, 1); 
// add upper 128 bits of sum to its lower 128 bits 
__m128d result = _mm_add_pd(sum_high, _mm256_castpd256_pd128(sum)); 
// lower 64 bits of result contain the sum of x1[0], x1[1], x1[2], x1[3] 
// upper 64 bits of result contain the sum of x2[0], x2[1], x2[2], x2[3] 

Vì vậy, nó trông giống như 3 hướng dẫn sẽ làm 2 số tiền ngang mà bạn cần. Ở trên là chưa được kiểm tra, nhưng bạn sẽ nhận được khái niệm.

+0

Đúng, giải pháp tuyệt vời. Cảm ơn Jason. @jason –

+0

Thay vì sử dụng đúc với (__m128d), tôi nghĩ bạn nên sử dụng _mm256_castpd256_pd128 (tổng). –

+0

Bạn đã sử dụng trình biên dịch nào cho điều này? Tôi hỏi một câu hỏi về diễn viên của bạn ở đây [c-style-cast-versus-intrinsic-cast] (http://stackoverflow.com/questions/20401413/c-style-cast-versus-intrinsic-cast). Tôi không có quyền truy cập vào hệ thống để kiểm tra điều này ngay bây giờ. –

5

Nếu bạn muốn chỉ là tiền, và một chút mã vô hướng có thể chấp nhận:

__m256d x; 
__m256d s = _mm256_hadd_pd(x,x); 
return ((double*)&s)[0] + ((double*)&s)[2]; 
3

Giả sử sau đây, bạn có một vector __m256d chứa 4 đôi đóng gói và bạn muốn tính tổng của thành phần của nó, tức là a0, a1, a2, a3 là mỗi thành phần đôi bạn muốn a0 + a1 + a2 + a3 sau đó heres một giải pháp AVX:

// goal to calculate a0 + a1 + a2 + a3 
__m256d values = _mm256_set_pd(23211.24, -123.421, 1224.123, 413.231); 

// assuming _mm256_hadd_pd(a, b) == a0 + a1, b0 + b1, a2 + a3, b2 + b3 (5 cycles) ... 
values = _mm256_hadd_pd(values, _mm256_permute2f128_pd(values, values, 1)); 
// ^^^^^^^^^^^^^^^^^^^^ a0 + a1, a2 + a3, a2 + a3, a0 + a1 

values = _mm256_hadd_pd(values, values); 
// ^^^^^^^^^^^^^^^^^^^^ (a0 + a1 + a2 + a3), (a0 + a1 + a2 + a3), (a2 + a3 + a0 + a1), (a2 + a3 + a0 + a1) 

// Being that addition is associative then each component of values contains the sum of all its initial components (11 cycles) to calculate, (1-2 cycles) to extract, total (12-13 cycles) 
double got = _mm_cvtsd_f64(_mm256_castpd256_pd128(values)), exp = (23211.24 + -123.421 + 1224.123 + 413.231); 

if (got != exp || _mm256_movemask_pd(_mm256_cmp_pd(values, _mm256_set1_pd(exp), _CMP_EQ_OS)) != 0b1111) 
    printf("Failed to sum double components, exp: %f, got %f\n", exp, got); 
else 
    printf("ok\n"); 

giải pháp này đã tổng phát sóng mà có thể hữu ích ...

012.

Nếu tôi hiểu sai vấn đề tôi xin lỗi.

$ uname -a 
Darwin Samys-MacBook-Pro.local 13.3.0 Darwin Kernel Version 13.3.0: Tue Jun 3 21:27:35 PDT 2014; root:xnu-2422.110.17~1/RELEASE_X86_64 x86_64 

$ gcc --version 
Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/usr/include/c++/4.2.1 
Apple LLVM version 5.1 (clang-503.0.40) (based on LLVM 3.4svn) 
Target: x86_64-apple-darwin13.3.0 
Thread model: posix 
Các vấn đề liên quan