繁体   English   中英

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

[英]SSE extracting integers from a __m128 for indexing an array

在我已经转换为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的浮点数将转换为值为1065353216的int。

如何正确地将__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]++;

这个版本摆脱了不必要的转换。 但是您需要使用不同的蒙版矢量。

编辑2:这是一种方式,你不必改变你的面具:

__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位数据类型转换,以__m128 C / C ++中的“类型”。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM