C++ 复制-浮点和AVX__m256的nan在复制后显示0

C++ 复制-浮点和AVX__m256的nan在复制后显示0,c++,copy,vectorization,simd,avx,C++,Copy,Vectorization,Simd,Avx,我有以下两种情况,对我来说应该是相似的,但显然不是 这一个不起作用,但这更理想: static union { __m256 trueMask8; float trueMask[8]; }; void Init() { trueMask8 = _mm256_cmp_ps(_mm256_setzero_ps(), _mm256_setzero_ps(), _CMP_EQ_OS); } class Ray8 { union { __m256 activeMask8; float dea

我有以下两种情况,对我来说应该是相似的,但显然不是

这一个不起作用,但这更理想:

static union { __m256 trueMask8; float trueMask[8]; };
void Init()
{
   trueMask8 = _mm256_cmp_ps(_mm256_setzero_ps(), _mm256_setzero_ps(), _CMP_EQ_OS);
}

class Ray8
{
   union { __m256 activeMask8; float deadMask[8]; };

   Ray8()
   {
      activeMask8 = trueMask8;
      int w = 0; //breakpoint
   }
}
上面的问题是activeMask8在断点上显示所有0,而trueMask8显示所有-nan,因此我确信Init已被调用

下面的一个可以工作,但不太理想,因为每次我需要一个真正的面具时,我都需要调用比较:

class Ray8
{
   union { __m256 activeMask8; float deadMask[8]; };

   Ray8()
   {
      activeMask8 = _mm256_cmp_ps(_mm256_setzero_ps(), _mm256_setzero_ps(), _CMP_EQ_OS);
       int w = 0; //breakpoint
   }
}
这里,activeMask8中的所有内容在断点处都是-1

这同样适用于:

activeMask[0] = trueMask[0];
这是两个浮动。trueMask[0]显示-nan,而activeMask[0]随后显示0


为什么会发生这种情况?我通常会尝试创建一个复制构造函数,但_m256是一个库类型。有解决方法吗?

因此,它与将trueMask8设置为true的范围有关。到目前为止,我无法在控制台程序中复制它,但我发现了以下几点:

在这两种情况下,我都将trueMask全局保存在我的ray.h文件中

如果在将其复制到activeMask8之前在Ray8()构造函数中设置trueMask,它将工作,并在程序的其余部分继续这样做

如果我在不是Ray8()构造函数的Init或构造函数中设置trueMask,它将不起作用。
我无法在控制台程序中重现这一点,所以我仍然不知道是什么原因造成的。但现在,它是一个解决方案,只需对我生成的每一条光线执行它。

因此,它与将trueMask8设置为true的范围有关。到目前为止,我无法在控制台程序中复制它,但我发现了以下几点:

在这两种情况下,我都将trueMask全局保存在我的ray.h文件中

如果在将其复制到activeMask8之前在Ray8()构造函数中设置trueMask,它将工作,并在程序的其余部分继续这样做

如果我在不是Ray8()构造函数的Init或构造函数中设置trueMask,它将不起作用。
我无法在控制台程序中重现这一点,所以我仍然不知道是什么原因造成的。但现在,它是一种解决方案,只需对我生成的每一条光线执行它。

我无法重现错误。你能提供一个完整的工作示例和你用来复制这个的命令吗?@jackw1111,真奇怪。我刚刚在一个控制台应用程序中测试了它,在那里它确实可以工作。我将尝试进一步缩小范围。感谢您指出这一点
\u mm256\u castsi256\u ps(\u mm256\u set1\u epi32(-1))
有什么问题?让编译器根据AVX2或AVX1是否可用来确定如何获取该位模式。它的编译效率应该相当高。不要让它从非常量
静态
联合加载;这不太可能更好。@Peter,除非我设置了static,否则它不会让我实现真正的全局掩码。问题是,我还需要在掩码中设置一个值,就像在上一个示例中一样。我想一个真正的掩码是一个很好的方法。等等,所以你的静态匿名联盟中的
trueMask8
不仅仅是一个常数?你想改变它吗?我的观点是,您通常不希望使用全局/静态
\uuuuum256
来保存
\umm256
内部初始值设定项的结果;即使您将其设置为常量,它也可以阻止常量传播。例如,您可以使用
-1
元素的
int
数组执行并初始化联合,以便可以静态初始化它。从理论上讲,这将允许编译器在您使用它的情况下进行不断的传播。对于非常量,您仍然可以这样做。我无法重现错误。你能提供一个完整的工作示例和你用来复制这个的命令吗?@jackw1111,真奇怪。我刚刚在一个控制台应用程序中测试了它,在那里它确实可以工作。我将尝试进一步缩小范围。感谢您指出这一点
\u mm256\u castsi256\u ps(\u mm256\u set1\u epi32(-1))
有什么问题?让编译器根据AVX2或AVX1是否可用来确定如何获取该位模式。它的编译效率应该相当高。不要让它从非常量
静态
联合加载;这不太可能更好。@Peter,除非我设置了static,否则它不会让我实现真正的全局掩码。问题是,我还需要在掩码中设置一个值,就像在上一个示例中一样。我想一个真正的掩码是一个很好的方法。等等,所以你的静态匿名联盟中的
trueMask8
不仅仅是一个常数?你想改变它吗?我的观点是,您通常不希望使用全局/静态
\uuuuum256
来保存
\umm256
内部初始值设定项的结果;即使您将其设置为常量,它也可以阻止常量传播。例如,您可以使用
-1
元素的
int
数组执行并初始化联合,以便可以静态初始化它。从理论上讲,这将允许编译器在您使用它的情况下进行不断的传播。对于非常量,您仍然可以这样做。如果
Init()
是从Ray8以外的构造函数运行的,那么您可能遇到了这样一个事实:静态对象的构造顺序没有定义。(又称静态初始化顺序失败。)最简单的解决方案是对联合使用常量初始化器,例如,它可以进入
.rodata
.data
,而不是仅运行时初始化。如果
Init()
是从Ray8以外的构造函数运行的,也许您遇到了这样一个事实:静态对象的构造顺序没有定义。(也称为静态初始化顺序失败。)最简单的解决方案是对联合使用常量初始化器,例如,这样它可以进入
.rodata
.data
,而不是只在运行时初始化。