c++ - 测试 256 位 YMM AVX 寄存器元素是否等于或小于零的最有效方法

标签 c++ x86 simd avx

我正在使用英特尔 AVX 内在函数实现粒子系统。当粒子的 Y 位置小于或等于零时,我想重置粒子。

粒子系统按照这样的 SOA 模式排序:

class ParticleSystem
{
    private:
        float*      mXPosition;
        float*      mYPosition;
        float*      mZPosition;

        .... Rest of code not important for this question

我想到的最初方法只是遍历 mYPosition 数组并检查开头所述的情况。也许使用这种方法可以提高一些性能?

但是问题是是否有任何有效的方法来实现这个 使用 AVX 内在函数?谢谢!

最佳答案

如果 <= 0 的元素相对稀疏,那么一种简单的方法是使用 AVX 一次测试 8 个,然后在识别包含一个或多个此类元素的 vector 时放入标量代码,例如:

#include <immintrin.h>                                  // AVX intrinsics

const __m256 vk0 = _mm256_setzero_ps();                 // const vector of zeros

for (int i = 0; i + 8 <= n; i += 8)
{
    __m256 vy = _mm256_loadu_ps(&mYPosition[i]);        // load 8 x floats
    __m256 vcmp = _mm256_cmp_ps(vy, vk0, _CMP_LE_OS);   // compare for <= 0
    int mask = _mm256_movemask_ps(vcmp);                // get MS bits from comparison result
    if (mask != 0)                                      // if any bits set
    {                                                   // then we have 1 or more elements <= 0
        for (int k = 0; k < 8; ++k)                     // test each element in vector
        {                                               // using scalar code...
            if ((mask & 1) != 0)
            {
                // found element at index i + k
                // do something with it...
            }
            mask >>= 1;
        }
    }
}
// deal with any remaining elements in case where n is not a multiple of 8
for (int j = i; j < n; ++j)
{
    if (mYPosition[j] <= 0.0f)
    {
        // found element at index j
        // do something with it...
    }
}

当然,如果匹配元素不是稀疏的,即如果您通常在每个 8 的 vector 中找到一个或多个元素,那么这不会给您带来任何性能提升。但是,如果元素稀疏,可以跳过大多数 vector ,那么您应该会看到显着的好处。

关于c++ - 测试 256 位 YMM AVX 寄存器元素是否等于或小于零的最有效方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30167995/

相关文章:

c++ - 有没有一种简单的方法可以将 C++ 枚举转换为字符串?

c++ - 使用 C++11 auto 关键字声明两个(或更多)变量

c++ - qmake:检测目标位宽(32 位或 64 位)

assembly - 相同的汇编指令但不同的机器指令

c++ - SSE:reinterpret_cast<__m128*> 而不是 _mm_load_ps

c++ - Altivec:_mm_sad_epu8() 的类似物

c++ - 标准是否保证了 lambda 的可继承性?

c# - 从其他异常的 StackTrace 获取 BadImageFormatException

assembly - 如何使用 rdtsc 在 Qemu i386 系统中进行基准测试

c - Altivec编译错误