【问题标题】:Copying -nan for float and AVX __m256 shows 0 after copying复制 -nan for float 和 AVX __m256 复制后显示 0
【发布时间】:2020-01-26 00:25:52
【问题描述】:

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

这个不行,这个会更理想:

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 是一种库类型。有解决办法吗?

【问题讨论】:

  • 我无法重现该错误。您能否提供一个完整的工作示例以及用于重现此示例的命令。
  • @jackw11111,这很奇怪。我也刚刚在控制台应用程序中对其进行了测试,并且确实可以正常工作。我将尝试进一步缩小范围。感谢您指出这一点
  • _mm256_castsi256_ps(_mm256_set1_epi32(-1)) 有什么问题?让编译器根据是否可用 AVX2 或仅 AVX1 来确定如何获取该位模式。它应该相当有效地编译。并且不要让它从非常量 static union 加载;这不太可能更好。
  • @Peter,除非我设置为静态,否则它不会让我将真正的掩码设为全局。问题是我还需要在掩码中设置一个值,就像在上一个示例中一样。我认为一个真正的面具会是一个很好的方式来做到这一点。
  • 等等,你的静态匿名联合中的trueMask8 不只是一个常数吗?您想要能够改变它吗?我的观点是,您通常不想使用全局/静态 __m256 来保存 _mm256 内在初始化程序的结果;即使您确实做到了const,它也可以击败持续传播。因此,例如,您将执行 godbolt.org/z/U7_Qh_ 并使用包含 -1 元素的 int 数组初始化联合,以便它可以静态初始化。这在理论上会让编译器在您使用它的情况下进行持续传播。您仍然可以对非常量执行此操作。

标签: c++ copy vectorization simd avx


【解决方案1】:

所以不知何故,它与将 trueMask8 设置为 true 的范围有关。到目前为止,我无法在控制台程序中重现它,但我发现了以下内容:

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

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

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

【讨论】:

  • 如果 Init() 是从 Ray8 以外的构造函数运行的,那么您可能会遇到这样一个事实,即未定义静态对象的构造顺序。 (又名静态初始化顺序惨败。)最简单的解决方案是为联合使用常量初始化器,例如 godbolt.org/z/U7_Qh_,因此它可以进入 .rodata.data,而不仅仅是运行时初始化。
猜你喜欢
  • 2016-05-09
  • 2013-08-21
  • 1970-01-01
  • 1970-01-01
  • 2013-09-18
  • 2014-07-28
  • 2019-01-26
  • 2013-03-24
  • 2011-10-17
相关资源
最近更新 更多