gpt4 book ai didi

c++ - SSE 从 __m128 中提取整数以索引数组

转载 作者:太空狗 更新时间:2023-10-29 21:06:10 25 4
gpt4 key购买 nike

在我已转换为 SSE 的一些代码中,我执行了一些光线追踪,使用 __m128 数据类型一次追踪 4 条光线。

在我确定首先击中哪些对象的方法中,我遍历所有对象,测试相交并创建一个掩码来表示哪些光线比之前找到的相交更早。

我还需要维护与最佳命中时间相对应的对象 ID 数据。为此,我维护了一个名为 objectNo 的 __m128 数据类型,并使用根据交集时间确定的掩码来更新 objectNo,如下所示:

objectNo = _mm_blendv_ps(objectNo,_mm_set1_ps((float)pobj->getID()),mask);

其中pobj->getID()会返回一个整数表示当前对象的id。进行此转换并使用混合似乎是更新所有 4 条光线的 objectNo 的最有效方法。

测试完所有交叉点后,我尝试单独提取 objectNo 并使用它们访问数组以注册交叉点。最常见的是我试过这个:

int o0 = _mm_extract_ps(objectNo, 0);
prv_noHits[o0]++;

然而,这会因 EXC_BAD_ACCESS 而崩溃,因为提取值为 1.0 的 float 会转换为值为 1065353216 的整数。

如何正确地将 __m128 解压缩为可用于索引数组的整数?

最佳答案

有两个 SSE2 转换内在函数似乎可以满足您的需求:

  • _mm_cvtps_epi32()
  • _mm_cvttps_epi32()

http://software.intel.com/sites/products/documentation/studio/composer/en-us/2011/compiler_c/intref_cls/common/intref_sse2_int_conversion.htm

这些会将 4 个单精度 FP 转换为 4 个 32 位整数。第一个是四舍五入。第二个使用截断。

所以它们可以这样使用:

int o0 = _mm_extract_epi32(_mm_cvtps_epi32(objectNo), 0);
prv_noHits[o0]++;

编辑:根据您尝试做的事情,我觉得这可以更好地优化如下:

__m128i ids = _mm_set1_epi32(pobj->getID());

// The mask will need to change
objectNo = _mm_blend_epi16(objectNo,ids,mask);

int o0 = _mm_extract_epi32(objectNo, 0);
prv_noHits[o0]++;

这个版本摆脱了不必要的转换。但是您需要使用不同的掩码 vector 。

编辑 2:这是一种无需更换 mask 的方法:

__m128 ids = _mm_castsi128_ps(_mm_set1_epi32(pobj->getID()));

objectNo = _mm_blendv_ps(objectNo,ids,mask);

int o0 = _mm_extract_ps(objectNo, 0);
prv_noHits[o0]++;

请注意,_mm_castsi128_ps() 内在函数不映射任何指令。这只是从 __m128i__m128 的逐位数据类型转换,以绕过 C/C++ 中的“类型”。

关于c++ - SSE 从 __m128 中提取整数以索引数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8077773/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com