如何使用SSE指令获取浮点数的倒数(反向),但仅用于非零值?
背景情况:
我想规范化一组向量,以便每个维度具有相同的平均值。在C中,这可以编码为:
float vectors[num * dim]; // input data
// step 1. compute the sum on each dimension
float norm[dim];
memset(norm, 0, dim * sizeof(float));
for(int i = 0; i < num; i++) for(int j = 0; j < dims; j++)
norm[j] += vectors[i * dims + j];
// step 2. convert sums to reciprocal of average
for(int j = 0; j < dims; j++) if(norm[j]) norm[j] = float(num) / norm[j];
// step 3. normalize the data
for(int i = 0; i < num; i++) for(int j = 0; j < dims; j++)
vectors[i * dims + j] *= norm[j];
现在出于性能原因,我想使用SSE intinsics来做到这一点。 Setp 1 et step 3很简单,但是我坚持第2步。我似乎没有找到任何代码示例或明显的SSE指令来获取值的recirpocal如果它不为零。 对于除法,_mm_rcp_ps可以解决问题,也可以将它与条件移动结合起来,但是如何获得一个掩码来指示哪个组件为零?
我不需要上述算法的代码,只需要“反向if not zero”函数:
__m128 rcp_nz_ps(__m128 input) {
// ????
}
谢谢!
答案 0 :(得分:13)
__m128 rcp_nz_ps(__m128 input) {
__m128 mask = _mm_cmpeq_ps(_mm_set1_ps(0.0), input);
__m128 recip = _mm_rcp_ps(input);
return _mm_andnot_ps(mask, recip);
}
如果输入为零,mask
的每个通道都设置为b111...11
,否则设置为b000...00
。并且 - 不使用该掩码替换对应于零输入的倒数元素。