什么时候转换为 __m256 而不是加载是正确的?
When is it correct to cast to __m256 instead of loading?
我有一个 32 字节对齐的结构,里面有 8 个向量:
struct ALIGN(32) Ray8
{
float x[8];
float y[8];
float z[8];
};
在使用AVX2的时候,想对这些成员进行统一操作。我什么时候需要使用 _mm256_load_ps() 显式加载它们而不是强制转换它们?例如,使用以下签名:
void GenerateRayDirections( __m256 * x, _m256 * y, _m256 * z ) { ... }
调用为
void GenerateRayDirections( (__m256*)ray.x, (__m256*)ray.y, (__m256*)ray.z );
我正在使用英特尔的 embree 库,他们有一个 vfloat8 class,它在内部将表示存储为 _m256 和 float8 的联合,因此根本没有转换 - 但似乎也没有加载调用.如果我改为嵌入 vfloat8 classes:
void GenerateRayDirections( &ray.x.v, &ray.y.v, &ray.z.v );
我正在寻找有关何时加载或投射的指导?
实际上,就生成的程序集而言,强制转换或调用 _mm256_load_ps
应该没有区别。正如您所指出的,您甚至可以通过联合获得所需的结果。
但是,所有这些都会在后台生成加载和存储 (vmov
) 指令。
为什么您更喜欢手动调用 _mm256_load_ps
?因为它迫使您考虑何时将数据从内存移动到向量寄存器。使用转换和联合的缺点是您可能不知道加载和存储。它们伴随着显着的延迟惩罚,比高级源代码可能表明的更糟糕。
使用像 _mm256_loadu_ps
这样的内在函数的另一个好处是您允许未对齐的内存访问而不会造成恶性崩溃。
我有一个 32 字节对齐的结构,里面有 8 个向量:
struct ALIGN(32) Ray8
{
float x[8];
float y[8];
float z[8];
};
在使用AVX2的时候,想对这些成员进行统一操作。我什么时候需要使用 _mm256_load_ps() 显式加载它们而不是强制转换它们?例如,使用以下签名:
void GenerateRayDirections( __m256 * x, _m256 * y, _m256 * z ) { ... }
调用为
void GenerateRayDirections( (__m256*)ray.x, (__m256*)ray.y, (__m256*)ray.z );
我正在使用英特尔的 embree 库,他们有一个 vfloat8 class,它在内部将表示存储为 _m256 和 float8 的联合,因此根本没有转换 - 但似乎也没有加载调用.如果我改为嵌入 vfloat8 classes:
void GenerateRayDirections( &ray.x.v, &ray.y.v, &ray.z.v );
我正在寻找有关何时加载或投射的指导?
实际上,就生成的程序集而言,强制转换或调用 _mm256_load_ps
应该没有区别。正如您所指出的,您甚至可以通过联合获得所需的结果。
但是,所有这些都会在后台生成加载和存储 (vmov
) 指令。
为什么您更喜欢手动调用 _mm256_load_ps
?因为它迫使您考虑何时将数据从内存移动到向量寄存器。使用转换和联合的缺点是您可能不知道加载和存储。它们伴随着显着的延迟惩罚,比高级源代码可能表明的更糟糕。
使用像 _mm256_loadu_ps
这样的内在函数的另一个好处是您允许未对齐的内存访问而不会造成恶性崩溃。