测试 256 位 YMM AVX 寄存器元素是否等于或小于零的最有效方法
Most efficient way to test a 256-bit YMM AVX register element for equal or less than zero
我正在使用英特尔 AVX 内部函数实现粒子系统。当粒子的Y轴位置小于或等于0时我想重置粒子
粒子系统按如下 SOA 模式排序:
class ParticleSystem
{
private:
float* mXPosition;
float* mYPosition;
float* mZPosition;
.... Rest of code not important for this question
我最初想到的方法只是遍历 mYPosition 数组并检查开头所述的情况。也许可以通过这种方法改进一些性能?
但是问题是是否有任何有效的方法来实现这个
使用 AVX 内在函数?谢谢!
如果 <= 0 的元素相对稀疏,那么一种简单的方法是使用 AVX 一次测试 8 个,然后在识别包含一个或多个此类元素的向量时放入标量代码,例如:
#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 的向量中找到一个或多个元素,那么这不会给您带来任何性能提升。但是,如果元素稀疏,可以跳过大多数向量,那么您应该会看到显着的好处。
我正在使用英特尔 AVX 内部函数实现粒子系统。当粒子的Y轴位置小于或等于0时我想重置粒子
粒子系统按如下 SOA 模式排序:
class ParticleSystem
{
private:
float* mXPosition;
float* mYPosition;
float* mZPosition;
.... Rest of code not important for this question
我最初想到的方法只是遍历 mYPosition 数组并检查开头所述的情况。也许可以通过这种方法改进一些性能?
但是问题是是否有任何有效的方法来实现这个 使用 AVX 内在函数?谢谢!
如果 <= 0 的元素相对稀疏,那么一种简单的方法是使用 AVX 一次测试 8 个,然后在识别包含一个或多个此类元素的向量时放入标量代码,例如:
#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 的向量中找到一个或多个元素,那么这不会给您带来任何性能提升。但是,如果元素稀疏,可以跳过大多数向量,那么您应该会看到显着的好处。