For the following simple example
static inline void Sum16FloatValuesN(float *dst, const float **src, size_t src_num) {
__m256 m_dst_1 = _mm256_loadu_ps(dst); // NOLINT
__m256 m_dst_2 = _mm256_loadu_ps(dst + 8); // NOLINT
__m256 m_src; // NOLINT
for (int i = 0; i < src_num; i++) {
m_src = _mm256_loadu_ps(src[i]); // NOLINT
m_dst_1 = _mm256_add_ps(m_dst_1, m_src); // NOLINT
m_src = _mm256_loadu_ps(src[i] + 8); // NOLINT
m_dst_2 = _mm256_add_ps(m_dst_2, m_src); // NOLINT
}
_mm256_storeu_ps(dst, m_dst_1); // NOLINT
_mm256_storeu_ps(dst + 8, m_dst_2); // NOLINT
}
static inline void Sum16FloatValuesN2(float *dst, const float **src, size_t src_num) {
for (int i = 0; i < src_num; i++)
for (int j = 0; j < 16; ++j)
dst[j] += src[i][j];
}
Use -O3 -march=haswell
to compile. From the assembly, I found that clang’s automatic vectorization optimization uses the xmm
register. And I tried to increase the size of dst
from 16 to 64, clang will also choose the ymm
register.
I have two questions to ask:
- For what reasons does the compiler not give priority to using ymm?
- Are there any parameters that can change this strategy? From an answer on stackoverflow, I learned about the -mprefer-vector-width=512 option, but the test did not work.