SSE内在函数用于比较(_mm_cmpeq_ps)和赋值操作

cub*_*war 1 c++ sse intrinsics

我已经开始使用SSE优化我的代码.基本上它是一个光线跟踪器,通过在__m128数据类型x,y,z中存储坐标,一次处理4条光线(四条光线的坐标按轴分组).但是,我有一个分支语句,可以防止除以零,我似乎无法转换为SSE.连续这是:

const float d = wZ == -1.0f ? 1.0f/( 1.0f-wZ) : 1.0f/(1.0f+wZ);
Run Code Online (Sandbox Code Playgroud)

其中wZ是z坐标,需要对所有四条射线进行计算.

我怎么能把它翻译成SSE?

我一直在尝试使用SSE等于比较如下(现在wz属于__m128数据类型,包含四条光线中每条光线的z值):

_mm_cmpeq_ps(_mm_set1_ps(-1.0f) , wZ )
Run Code Online (Sandbox Code Playgroud)

然后使用它来识别wZ [x] = -1.0的情况,取这个情况的绝对值,然后继续计算正常.

但是,我在这方面没有取得多大成功.

Pau*_*l R 5

这是一个相当简单的解决方案,只需使用SSE实现标量代码而无需进一步优化.它可能会更有效率,例如通过利用wZ = -1.0时结果为0.5的事实,或者甚至可以通过仅进行除法,然后在INF事后将s 转换为0.5.

#ifdef因为SSE4具有"混合"指令,这可能比掩盖和选择值所需的三个预SSE4指令更有效,因此我需要SSE4与SSE4之前的指令.

#include <emmintrin.h>
#ifdef __SSE4_1__
#include <smmintrin.h>
#endif

#include <stdio.h>

int main(void)
{
    const __m128 vk1 = _mm_set1_ps(1.0f);       // useful constants
    const __m128 vk0 = _mm_set1_ps(0.0f);

    __m128 wZ, d, d0, d1, vcmp;
#ifndef __SSE4_1__  // pre-SSE4 implementation
    __m128 d0_masked, d1_masked;
#endif

    wZ = _mm_set_ps(-1.0f, 0.0f, 1.0f, 2.0f);   // test inputs

    d0 = _mm_add_ps(vk1, wZ);                   // d0 = 1.0 - wZ
    d1 = _mm_sub_ps(vk1, wZ);                   // d1 = 1.0 + wZ
    vcmp = _mm_cmpneq_ps(d1, vk0);              // test for d1 != 0.0, i.e. wZ != -1.0
#ifdef __SSE4_1__   // SSE4 implementation
    d = _mm_blendv_ps(d0, d1, vcmp);
#else               // pre-SSE4 implementation
    d0_masked = _mm_andnot_ps(vcmp, d0);
    d1_masked = _mm_and_ps(vcmp, d1);
    d = _mm_or_ps(d0_masked, d1_masked);       // d = wZ == -1.0 ? 1.0 / (1.0 - wZ) : 1.0 / (1.0 + wZ)
#endif
   d = _mm_div_ps(vk1, d);

   printf("wZ = %vf\n", wZ);
   printf("d = %vf\n", d);

   return 0;
}
Run Code Online (Sandbox Code Playgroud)