[英]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()
这些将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.