我在for循环中有以下代码
dataInt = _mm_loadu_si128((__m128i *) (&x[i]));
__m256i val_unpacked = _mm256_cvtepi16_epi32(dataInt);
__m256 converted = _mm256_cvtepi32_ps(val_unpacked);
converted = _mm256_div_ps(converted, _mm256_set1_ps(max_val));
_mm256_storeu_ps(&y[i], converted);
_mm256_zeroupper();
它基本上只是将int16的向量转换为[-1,1]范围内的浮点数(max_val是const变量,等于numeric_limit :: max)。
我在posix线程版本7.2中使用mingw编译器
当我在没有优化的情况下编译程序时,它运行得很好,但是当我打开优化时(我无法控制单个优化,它在我正在研究的项目内部,但是应该使用lvl of优化-O3),我开始得到错误的结果。
问题出在zeroupper指令中。当我在优化模式下将其删除时,它再次给出了正确的结果。
看似优化没有考虑到zeroupper指令的放置,而是在循环的中间而不是在结尾处调用它,从而丢弃了有用的数据。这样有可能吗?我在互联网上找不到有关此主题的任何讨论。
编辑:我提取了代码。看起来像这样:
#include <iostream>
#include <limits>
#include <immintrin.h>
#include <xmmintrin.h>
int __attribute__ ((__target__ ("avx2,sse4.2"))) main(){
/*volatile*/ float max_val = static_cast<float> (std::numeric_limits<int16_t>::max());
__m128i dataInt;
int runs = 32;
int16_t source[32];
float target[32];
int i = 0;
for (; i < 32; ++i) {
source[i] = std::numeric_limits<int16_t>::min()+i;
}
i=0;
for (; i < runs; i += 8) {
// _mm256_zeroupper();
dataInt = _mm_loadu_si128((__m128i *) (&source[i]));
__m256i val_unpacked =_mm256_cvtepi16_epi32(dataInt);
__m256 converted = _mm256_cvtepi32_ps(val_unpacked);
__m256 maxVinFloat = _mm256_set1_ps(max_val);
converted = _mm256_div_ps(converted, maxVinFloat);
_mm256_storeu_ps(&target[i], converted);
_mm256_zeroupper();
}
i = 0;
for (; i < 32; ++i) {
std::cout << target [ i ] <<" ";
}}
但是,当使用在线编译器进行编译时,即使使用lvl 3优化,输出也可以。但是我在原始文章中描述的使用编译器的Clion输出了无穷多个,因为具有最大值的寄存器maxVinFloat由寄存器一半的零组成。因此,似乎寄存器已优化为仅初始化一次,并且循环输出无穷大的其他迭代。
EDIT2:我的错误,它确实会在在线编译器上输出无穷大,但是我忘了在测试它时删除易失性部分(解决了问题),只是运行该代码 这里https://www.tutorialspoint.com/compile_cpp_online.php具有-O2优化