Ben*_*Uri 4 c performance sse vectorization avx
我可以拥有这样的工会吗?
union eight_floats_t
{
__m256 a;
__m128 b[2];
};
eight_floats_t eight_floats;
Run Code Online (Sandbox Code Playgroud)
能够即时访问256位寄存器的两个128位部分吗?
编辑:我要求了解这种方法对性能的影响.
Mys*_*ial 10
你当然可以做到这一点.C和C++语言允许您这样做.它很可能会做你想做的事情.
但是,您使用AVX的事实意味着您关心性能.因此,知道这是SSE程序员陷入的最常见(性能)陷阱之一可能是有用的.(许多人没有注意到)
问题1:
当前的编译器使用存储器位置实现这种联合.所以这是第一个问题,每次从不同的字段访问联合时,它都会强制数据到内存并将其读回.这是一个减速.
以下是MSVC2010为其生成的内容(通过优化):
eight_floats a;
a.a = vecA[0];
__m128 fvecA = a.b[0];
__m128 fvecB = a.b[1];
fvecA = _mm_add_ps(fvecA,fvecB);
Run Code Online (Sandbox Code Playgroud)
vmovaps YMMWORD PTR a$[rbp], ymm0
movaps xmm1, XMMWORD PTR a$[rbp+16]
addps xmm1, XMMWORD PTR a$[rbp]
movaps XMMWORD PTR fvecA$[rbp], xmm1
movss xmm1, DWORD PTR fvecA$[rbp]
Run Code Online (Sandbox Code Playgroud)
你可以看到它被刷新到内存中.
问题2:
第二次放缓甚至更糟.当您向内存写入内容并立即使用不同的字大小访问它时,您可能会触发存储到加载停顿.(通常大于10个周期)
这是因为当前处理器上的加载存储队列通常不是为处理这种(异常)情况而设计的.所以他们通过简单地将队列刷新到内存来处理它.
访问AVX数据类型的上半部分和上半部分的"正确"方法是使用:
_mm256_extractf128_ps()_mm256_insertf128_ps()_mm256_castps256_ps128()和家人.同样对于其他数据类型也是如此.
也就是说,编译器可能足够聪明,无法识别您正在做什么并使用这些指令.(至少MSVC2010没有.)