*(__m128*)(&A) 和 (__m128)A 有啥区别
Posted
技术标签:
【中文标题】*(__m128*)(&A) 和 (__m128)A 有啥区别【英文标题】:what is difference between *(__m128*)(&A) and (__m128)A*(__m128*)(&A) 和 (__m128)A 有什么区别 【发布时间】:2021-03-22 09:46:07 【问题描述】:*(B*)(&A)
和 (B)A
有什么区别
我正在使用 simd 代码。但我遇到了问题。
我无法将自己的 vector4
类型转换为 __m128
所以我确实喜欢这个 这很好用
#define XMM128Float(VECTOR4FLOAT) *(__m128*)(&VECTOR4FLOAT)
Vector4<float> vec4;
XMM128Float(&vec4) = _mm_mul_ps(XMM128Float(*this), XMM128Float(*this));
我想知道为什么(__m128)vec4
不起作用....
它们之间有什么区别。
#define XMM128Float(VECTOR4FLOAT) *(__m128*)(&VECTOR4FLOAT)
template <>
[[nodiscard]] inline SIMD_CONSTEXPR auto Vector<4, float>::sqrMagnitude() const noexcept
Vector<4, float> Result;
XMM128Float(Result) = _mm_mul_ps(XMM128Float(*this), XMM128Float(*this));
return Result.x + Result.y + Result.z + Result.w;
我这样写了我的 SIMD 函数。
我正在使用 MS BUILD 16 编译器
【问题讨论】:
其中一个是明确定义的:D @M.M:与人们可能猜到的不同(根据正常的 C++ 严格别名规则),定义明确的是指针转换:Is `reinterpret_cast`ing between hardware SIMD vector pointer and the corresponding type an undefined behavior?。尽管在 MSVC 中,指针转换类型的双关语总是定义明确的(只要您不读取数组或结构之外的内容):MSVC 就像gcc -fno-strict-aliasing
。
@PeterCordes Re“在 MSVC 指针转换类型中,双关语总是明确定义的”:这是官方记录的吗?用-Ox
(最大优化)编译时也是这样吗?
@njuffa:是的,但我现在找不到。我很确定我已经看过 MSDN 文档,其中建议执行reinterpret_cast<float&>(my_unsigned)
或等效*(float*)&my_unsigned
之类的操作。开发人员也广泛接受 MSVC 不会破坏严格的别名,并且他们无法在不破坏现有代码的情况下引入基于类型的别名优化,但正如我所说,我认为 MS 确实接受了这些习惯用法。 (也许是用不可移植的代码将人们锁定在他们的编译器中,或者让 GCC/clang 在“破坏他们的代码”时看起来很糟糕?)
@PeterCordes 作为一名退休的软件工程师,我的 0.02 美元,他的整个职业生涯都在行业中:总的来说(除了例外)企业尽量不使现有客户的代码库失效。除此之外,有时他们会竭尽全力保持损坏的客户代码正常工作。在 Microsoft 的案例中,其中一些客户可能是内部客户。开源项目很少以类似的方式受到限制,并且直截了当地指导用户修复他们的非标准兼容代码(我发现自己曾经处于接收端,使用 gcc:已使用近 20 年的代码中的有符号整数溢出年)。
【参考方案1】:
*(B*)(&A)
和(B)A
有什么区别
*(B*)(&A)
使用addressof 操作符得到A
命名的对象的地址,然后将该指针显式转换1 到另一个指针类型B*
,然后通过 2 转换后的指针。
(B)A
将A
命名的对象显式转换为B
类型的新对象。
我想知道为什么 (__m128)vec4 不起作用....
您不能将类类型A
的值转换为另一种类型B
,除非您为A
定义了一个可以转换为B
类型或其他可转换为@987654334 的类型的转换运算符@(或者除非B
也是一个类并且具有接受A
参数或可转换为A
的另一种类型的转换构造函数) - 请注意,在一个转换序列中只能使用一个这样的用户定义转换;其他转换必须是标准转换。
1 不要在 C++ 中使用显式转换,即 C 样式转换。请改用特定的static_cast
、reinterpret_cast
和const_cast
。
2 请注意,通过重新解释的指针访问对象通常可能会导致未定义的行为,具体取决于所涉及的类型。仅在特定情况下才允许。请查阅您的编译器手册,了解__m128
是否属于这种情况。
附:避免不必要的宏。你写的东西可以定义为内联函数。
【讨论】:
一些编译器对 SIMD 类型有特殊的语义... @MarcGlisse 你具体有什么想法? Gcc 允许在向量类型之间进行一些转换(更多-flax-vector-conversions
),其语义与指针转换相同,而不是转换。
我可以缩短这个代码#define XMM128Float(VECTOR4FLOAT) *(__m128*)(&VECTOR4FLOAT)
@MarcGlisse 似乎不适用于类:godbolt.org/z/T76jnc884(任何阅读者的旁注,请注意文档中说“此选项不应用于新代码。”)以上是关于*(__m128*)(&A) 和 (__m128)A 有啥区别的主要内容,如果未能解决你的问题,请参考以下文章