2012-03-19 12 views
12

Mam zapakowany wektor czterech 64-bitowych wartości zmiennoprzecinkowych.
Chciałbym uzyskać sumę elementów wektora.Najszybszy sposób na zrobienie sumy wektorowej z instrukcjami AVX

Z SSE (i przy użyciu 32-bitowych pływaków) może po prostu wykonaj następujące czynności:

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

Niestety, mimo AVX oferuje dyspozycję _mm256_hadd_pd, różni się w wyniku z wersji SSE. Sądzę, że wynika to z faktu, że większość instrukcji AVX działa jako instrukcje SSE dla każdego niskiego i wysokiego 128-bitowego oddzielnie, bez przekraczania granicy 128-bitowej.

Idealne rozwiązanie, którego szukam, powinno być zgodne z następującymi wytycznymi:
1) stosować wyłącznie instrukcje AVX/AVX2. (bez SSE)
2) zrób to w nie więcej niż 2-3 instrukcjach.

Jednak każdy efektywny/elegancki sposób to zrobić (nawet bez przestrzegania powyższych wytycznych) jest zawsze dobrze przyjęty.

Wielkie dzięki za pomoc.

-Luigi Castelli

+0

Rozpocznij '_mm256_extractf128_ps'' _mm_add_ps' dwóch części razem, a następnie użyć [istniejące sposoby redukcji 128b wektor] (http://stackoverflow.com/questions/6996764/fastest-way-to -do-poziomej-float-wektor-sum-na-x86). –

Odpowiedz

17

Jeśli masz dwie __m256d wektory x1 i x2 z których każdy zawiera cztery double s, które mają być poziomo sumę, można zrobić:

__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] 

Wygląda więc na to 3 instrukcje zrobi 2 z horyzontalnych sum, których potrzebujesz. Powyższe jest niesprawdzone, ale powinieneś dostać tę koncepcję.

+0

Tak, świetne rozwiązanie. Dzięki Jason. @jason –

+0

Zamiast używać rzutowania z (__m128d) myślę, że powinieneś użyć _mm256_castpd256_pd128 (suma). –

+0

Jaki kompilator używałeś do tego? Zadałem pytanie o twoją obsadę [c-style-cast-versus-intrinsic-cast] (http://stackoverflow.com/questions/20401413/c-style-cast-versus-intrinsic-cast). Nie mam dostępu do systemu, aby przetestować to teraz. –

5

Jeśli chcesz tylko sumę, i trochę kodu skalarnego jest dopuszczalne:

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

się przyjmując, że masz __m256d wektor zawierający 4 zapakowane podwójne i chcesz obliczyć sumę jego części, tj a0, a1, a2, a3 jest każdy dwukomponentowy chcesz a0 + a1 + a2 + a3 następnie heres inne rozwiązanie 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"); 

rozwiązanie to suma, która może być przydatna transmitowane ...

Jeśli źle zinterpretowałem problem, przepraszam.

$ 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 
Powiązane problemy