加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c – 使用AVX后,SSE运行缓慢

发布时间:2020-12-16 05:34:45 所属栏目:百科 来源:网络整理
导读:我有一些奇怪的问题,一些SSE2和AVX代码我一直在努力.我使用GCC构建我的应用程序,哪个运行时cpu功能检测.目标文件是用每个CPU功能的分离标记构建的,例如: g++ -c -o ConvertSamples_SSE.o ConvertSamples_SSE.cpp -std=c++11 -fPIC -O0 -g -Wall -I./include
我有一些奇怪的问题,一些SSE2和AVX代码我一直在努力.我使用GCC构建我的应用程序,哪个运行时cpu功能检测.目标文件是用每个CPU功能的分离标记构建的,例如:
g++ -c -o ConvertSamples_SSE.o ConvertSamples_SSE.cpp -std=c++11 -fPIC -O0 -g -Wall -I./include -msse
g++ -c -o ConvertSamples_SSE2.o ConvertSamples_SSE2.cpp -std=c++11 -fPIC -O0 -g -Wall -I./include -msse2
g++ -c -o ConvertSamples_AVX.o ConvertSamples_AVX.cpp -std=c++11 -fPIC -O0 -g -Wall -I./include -mavx

当我第一次启动该程序时,我发现SSE2例程与正常情况相同,在非SSE例程中的速度提升很快(大约100%更快).在运行任何AVX例程后,完全相同的SSE2例程现在运行得比较慢.

有人可以解释这是什么原因?

在AVX程序运行之前,所有的测试比FPU数学运算快80到130%,这在这里可以看出,在AVX程序运行之后,SSE例程要慢得多.

如果我跳过AVX测试例程,我从来没有看到这种性能损失.

这是我的SSE2例程

void Float_S16(const float *in,int16_t *out,const unsigned int samples)
{
  static float  ratio = (float)Limits<int16_t>::range() / (float)Limits<float>::range();
  static __m128 mul   = _mm_set_ps1(ratio);

  unsigned int i;
  for (i = 0; i < samples - 3; i += 4,in += 4,out += 4)
  {
    __m128i con = _mm_cvtps_epi32(_mm_mul_ps(_mm_load_ps(in),mul));
    out[0] = ((int16_t*)&con)[0];
    out[1] = ((int16_t*)&con)[2];
    out[2] = ((int16_t*)&con)[4];
    out[3] = ((int16_t*)&con)[6];
  }

  for (; i < samples; ++i,++in,++out)
    *out = (int16_t)lrint(*in * ratio);
}

而AVX版本也一样.

void Float_S16(const float *in,const unsigned int samples)
{
  static float ratio = (float)Limits<int16_t>::range() / (float)Limits<float>::range();
  static __m256 mul  = _mm256_set1_ps(ratio);

  unsigned int i;
  for (i = 0; i < samples - 7; i += 8,in += 8,out += 8)
  {
    __m256i con = _mm256_cvtps_epi32(_mm256_mul_ps(_mm256_load_ps(in),mul));
    out[0] = ((int16_t*)&con)[0];
    out[1] = ((int16_t*)&con)[2];
    out[2] = ((int16_t*)&con)[4];
    out[3] = ((int16_t*)&con)[6];
    out[4] = ((int16_t*)&con)[8];
    out[5] = ((int16_t*)&con)[10];
    out[6] = ((int16_t*)&con)[12];
    out[7] = ((int16_t*)&con)[14];
  }

  for(; i < samples; ++i,++out)
    *out = (int16_t)lrint(*in * ratio);
}

我也通过valgrind运行它,检测没??有错误.

解决方法

混合AVX代码和旧版SSE代码会导致性能损失.最合理的解决方案是在AVX段代码之后执行VZEROALL指令,特别是在执行SSE代码之前.

根据英特尔的图表,转换到或退出状态C(保留了AVX寄存器的上半部分的传统SSE)的转换时间为100个时钟周期.其他转换只有1个周期:

参考文献:

> Intel: Avoiding AVX-SSE Transition Penalties
> Intel? AVX State Transitions: Migrating SSE Code to AVX

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读