root/software/misc/ps_test.cc @ 9ee3a995
| edd171a6 | David Sorber | #include <iostream>
|
|
#include <x86intrin.h>
|
|||
// Return horizontal sum for 128 bit packed float vector
|
|||
float hsum_ps_sse3(__m128 val)
|
|||
{
|
|||
__m128 shuf = _mm_movehdup_ps(val); // broadcast elements 3,1 to 2,0
|
|||
__m128 sums = _mm_add_ps(val, shuf);
|
|||
shuf = _mm_movehl_ps(shuf, sums); // high half -> low half
|
|||
sums = _mm_add_ss(sums, shuf);
|
|||
return _mm_cvtss_f32(sums);
|
|||
}
|
|||
// Return horizontal sum for 256 bit packed float vector
|
|||
// https://stackoverflow.com/a/35270026/73878 -- Peter Cordes is da man
|
|||
float hsum256_ps_avx(__m256 val)
|
|||
{
|
|||
__m128 vlow = _mm256_castps256_ps128(val);
|
|||
__m128 vhigh = _mm256_extractf128_ps(val, 1); // high 128
|
|||
vlow = _mm_add_ps(vlow, vhigh); // add the low 128
|
|||
return hsum_ps_sse3(vlow); // and inline the sse3 version, which is optimal for AVX
|
|||
}
|
|||
void print_debug(__m256 val)
|
|||
{
|
|||
float temp[8];
|
|||
_mm256_store_ps(temp, val);
|
|||
std::cout << "DEBUG: "
|
|||
<< temp[0] << " -- " << temp[1] << " -- "
|
|||
<< temp[2] << " -- " << temp[3] << " -- "
|
|||
<< temp[4] << " -- " << temp[5] << " -- "
|
|||
<< temp[6] << " -- " << temp[7] << std::endl;
|
|||
}
|
|||
// Return max value across (i.e. horizontally) vector
|
|||
// Algorithm came from here: https://stackoverflow.com/a/9798369/73878
|
|||
float max_ps_avx(__m256 val)
|
|||
{
|
|||
__m256 m0 = _mm256_permute2f128_ps(val, val, 1); // Permute 128-bit values
|
|||
__m256 m1 = _mm256_max_ps(val, m0); // Compute max of 4 sets
|
|||
__m256 m2 = _mm256_permute_ps(m1, 0x4E); // Permute max values
|
|||
__m256 m3 = _mm256_max_ps(m1, m2); // Compute max of 2 sets
|
|||
__m256 m4 = _mm256_permute_ps(m3, 0x3B); // Permute max values
|
|||
__m256 m = _mm256_max_ps(m3, m4); // Compute (final) max
|
|||
return _mm_cvtss_f32(_mm256_extractf128_ps(m, 0));
|
|||
}
|
|||
// Return min value across (i.e. horizontally) vector
|
|||
// Algorithm came from here: https://stackoverflow.com/a/9798369/73878
|
|||
float min_ps_avx(__m256 val)
|
|||
{
|
|||
__m256 m0 = _mm256_permute2f128_ps(val, val, 1); // Permute 128-bit values
|
|||
__m256 m1 = _mm256_min_ps(val, m0); // Compute min of 4 sets
|
|||
__m256 m2 = _mm256_permute_ps(m1, 0x4E); // Permute max values
|
|||
__m256 m3 = _mm256_min_ps(m1, m2); // Compute min of 2 sets
|
|||
__m256 m4 = _mm256_permute_ps(m3, 0x3B); // Permute max values
|
|||
__m256 m = _mm256_min_ps(m3, m4); // Compute (final) min
|
|||
return _mm_cvtss_f32(_mm256_extractf128_ps(m, 0));
|
|||
}
|
|||
// g++ -std=c++11 -O3 -mavx -o ps_test ps_test.cc
|
|||
int main(int argc, char** argv)
|
|||
{
|
|||
std::cout << "Packed Float (PS) Test\n" << std::endl;
|
|||
float raw_data[8] = {1.0, 2.0, -3.0, 4.0, 5.0, -6.0, 7.0 , 8.0};
|
|||
// Generate signmask
|
|||
__m256 SIGNMASK = _mm256_castsi256_ps(_mm256_set1_epi32(0x80000000));
|
|||
// Load data
|
|||
__m256 data = _mm256_loadu_ps(raw_data);
|
|||
// Take absolute value of data
|
|||
__m256 abs_data = _mm256_andnot_ps(SIGNMASK, data);
|
|||
// Sum data
|
|||
float total = hsum256_ps_avx(data);
|
|||
float total_abs = hsum256_ps_avx(abs_data);
|
|||
std::cout << "Total: " << total << " -- " << total_abs << std::endl;
|
|||
std::cout << " Max: " << max_ps_avx(abs_data) << std::endl;
|
|||
std::cout << " Min: " << min_ps_avx(abs_data) << std::endl;
|
|||
return 0;
|
|||
}
|