SIMD:在执行期间寄存器改变值

Posted

技术标签:

【中文标题】SIMD:在执行期间寄存器改变值【英文标题】:SIMD : registers changing value during execution 【发布时间】:2018-01-25 04:19:12 【问题描述】:

所以此刻我的代码中发生了一些奇怪的事情,它是关于以下寄存器__m256i local,在某处计算期间分配,以及__m256i mask,与本地无关。

在哪里运行以下:

  std::cout << _mm256_extract_epi32 (local, 0) << ", " << _mm256_extract_epi32(local,1) << ", " << _mm256_extract_epi32(local,2) << ", " << _mm256_extract_epi32(local,3) << ", " << _mm256_extract_epi32(local,4) << ", " << _mm256_extract_epi32(local,5) << ", " << _mm256_extract_epi32(local,6) << ", " << _mm256_extract_epi32(local,7) << std::endl;

  for (int l = 0; l < 8; ++l)
  
    if (mask[l]) mask[l] = 0; else mask[l] = 1;
  
  std::cout << _mm256_extract_epi32 (local, 0) << ", " << _mm256_extract_epi32(local,1) << ", " << _mm256_extract_epi32(local,2) << ", " << _mm256_extract_epi32(local,3) << ", " << _mm256_extract_epi32(local,4) << ", " << _mm256_extract_epi32(local,5) << ", " << _mm256_extract_epi32(local,6) << ", " << _mm256_extract_epi32(local,7) << std::endl;`

我为第一个输出获得519, 519, 519, 519, 519, 519, 519, 519,为第二个输出获得0, 0, 0, 0, 0, 0, 0, 0,即使它们来自同一个寄存器。知道怎么会发生这样的事情吗?

【问题讨论】:

这不是minimal reproducible example,因为它缺少localmask 的定义,包括这些变量如何获取它们的值。 【参考方案1】:

您的 for 循环的意图是访问 256 位 mask 向量中的 32 位字吗?这不是正确的做法。当您使用下标运算符访问mask 时,编译器会超出实际mask 变量在内存中的位置,并破坏其后面的7x 256 字节区域。

如果您想轻松访问 mask 中的 32 位字,请尝试将其声明为:

union vec8x32_t

  __m256i  vector;
  uint32_t words[8];
;

vec8x32_t mask;

然后你可以这样做:

// Do some AVX thing with mask:
mask.vector = _mm256_set_epi32(0, 1, 0, 1, 0, 1, 0, 1);

// Manipulate the components of mask:
for (int l = 0; l < 8; ++l)

  if (mask.words[l]) mask.words[l] = 0; else mask.words[l] = 1;

【讨论】:

OP 的代码,如所示,不会编译。如果您查看__m256i 的定义(在&lt;immintrin.h&gt; 中),您会发现它已经是一个联合,而您的联合是不必要的。 @1201ProgramAlarm,这似乎与编译器有关。我确实在 MSVC 2015 中看到了该定义,但 GCC 7 没有提供它,抱怨:error: request for member ‘m256i_u32’ in ‘mask’, which is of non-class type ‘__m256i aka __vector(4) long long int’. 那么 GCC 没有使用标准的 Intel 头文件。叹息。

以上是关于SIMD:在执行期间寄存器改变值的主要内容,如果未能解决你的问题,请参考以下文章

SIMD (AVX2) - 将 uint8_t 值加载到多个浮点 __m256 寄存器

可以通过使用输入寄存器来寻址输出 SIMD 寄存器

将数据放入 SIMD 寄存器需要多少个周期?

有没有一种有效的方法来使用 SIMD 内在函数来获取 SIMD 寄存器中的第一个非零元素?

armv8-a:测试 SIMD 寄存器是不是为 != 0

1. SIMD发展历程