将 __m128i 值转换为 std::tuple
Posted
技术标签:
【中文标题】将 __m128i 值转换为 std::tuple【英文标题】:Convert __m128i value into std::tuple 【发布时间】:2017-05-12 12:14:27 【问题描述】:想象一下,经过一些 SIMD 计算,我得到一个 __m128i
值,其中第四个字段的值为零。是否有一种简单便携的方法可以将其他三个字段转换为std::tuple<int,int,int>
,记住它不是standard layout?
【问题讨论】:
“简单”经常与“便携”和/或“符合标准”相冲突。std::tuple<int, int, int>
不要求具有标准布局。但是,您可能会发现大多数实现产生的内存布局与您预期的一样。如果是这种情况,如果不要求严格遵守标准,您脑海中已有的实现可能会起作用。由于您引用了__m128i
,因此您使用的是x86,所以我不考虑int
可能有的任何奇怪的填充/对齐要求; __m128i
的布局与 int[4]
一样。
@JasonR:tuple
的字段顺序未指定...所以 “可能工作” 对 IMO 过于乐观。
@Jason R 实际上,对于 x86 平台上的 SIMD 'm128' _requires 对齐(16)
@Jarod42:也许吧。给 OP 的教训可能是不,没有可移植或符合标准的方法来做到这一点。话虽如此,有很多 C++ 代码并不完全符合标准。如果您可以绑定您的一组平台和编译器/库版本,并且您愿意承担未来可能出现的维护难题,那么这可能是可能的。
@Swift:我从事类似的项目。我鼓励您将_mm_load_ps()
更改为_mm_loadu_ps()
进行基准测试。您会发现,在类似的条件下,它们的性能基本上无法区分;您使用的指令的选择并不重要。话虽如此,对齐加载可以更快,因为它们保证不会跨越缓存行或页面边界,但使用哪种类型的指令并不重要。假设未对齐的 128 位内存操作可以简化您的代码结构并放松对输入和输出的约束。
【参考方案1】:
丑陋,但便携。我不相信有快速的解决方案,因为std::tuple
没有定义内存布局。所以只需将这三个值复制到一个元组中。
std::tuple<int, int, int> to_tuple(__m128i& value)
auto* ptr = reinterpret_cast<int*>(&value);
return std::make_tuple(ptr[0], ptr[1], ptr[2]);
为什么需要这个?也许您可以通过其他方式解决您的问题。
【讨论】:
这就是我正在做的,尽管使用_mm_storeu_si128
而不是reinterpret_cast
,但我认为生成的程序集是相同的。我希望有一个更优雅的解决方案......以上是关于将 __m128i 值转换为 std::tuple的主要内容,如果未能解决你的问题,请参考以下文章
将 16 位值的 __m256i 打包(饱和)到 8 位值的 __m128i?