【发布时间】: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 来确定如何获取该位模式。它应该相当有效地编译。并且不要让它从非常量staticunion 加载;这不太可能更好。 -
@Peter,除非我设置为静态,否则它不会让我将真正的掩码设为全局。问题是我还需要在掩码中设置一个值,就像在上一个示例中一样。我认为一个真正的面具会是一个很好的方式来做到这一点。
-
等等,你的静态匿名联合中的
trueMask8不只是一个常数吗?您想要能够改变它吗?我的观点是,您通常不想使用全局/静态__m256来保存_mm256内在初始化程序的结果;即使您确实做到了const,它也可以击败持续传播。因此,例如,您将执行 godbolt.org/z/U7_Qh_ 并使用包含-1元素的int数组初始化联合,以便它可以静态初始化。这在理论上会让编译器在您使用它的情况下进行持续传播。您仍然可以对非常量执行此操作。
标签: c++ copy vectorization simd avx