Vector256.Create 和 Avx2.BroadcastScalarToVector 函数有什么区别?

What are the differences between Vector256.Create and Avx2.BroadcastScalarToVector functions?

例如,我想创建一个Vector256变量,所有元素都初始化为指定的有符号整数,假设我的系统支持Avx2。 .NET 文档说使用 Avx2 广播 scarlar 使用 _mm256_broadcastd_epi32_mm_broadcastd_epi32 指令。

Vector256.Create生成什么指令?是不是和上面一样?

int value = -1;
Vector256<int> v1 = Avx2.BroadcastScalarToVector256(&value);
Vector256<int> v2 = Vector256.Create(-1);
Debug.Assert(v1.Equals(v2)); // True

TL/DR:当源数据在内存中时使用BroadcastScalarToVector256,在所有其他情况下使用Vector256<int>.Create

BroadcastScalarToVector256 的文档说它编译成这个程序集:VPBROADCASTD ymm, m32 当源标量在内存中时,这是你想要的,但如果源数据是一个寄存器。即使内存在堆栈上,即在 L1D 缓存上,往返在延迟方面稍微慢一些。

Vector256.Create( int )的文档没有说编译成什么,只说它对应于C++中的_mm256_set1_epi32 intrinsic。这意味着 JIT 编译器可以自由地做任何最有效的事情。

如果您调用 Vector256<int>.Create( 0 ),它应该编译成 vpxor ymm0, ymm0, ymm0 指令,因为该指令是将向量置零的快速方法。

当您调用 Vector256<int>.Create( -1 ) 时,它应该编译成 vpcmpeqd ymm0, ymm0, ymm0 指令或类似指令,再次因为编译器已知该值,vpcmpeqd 没有数据依赖性,并且可以完成工作,快。

当你在那里传递一个变量时,Create 应该编译成像 vmovd xmm0, eax; vpbroadcastd ymm0, xmm0 这样的代码,这是两条指令,但仍然比往返内存和返回更快。