我正在编写一些对性能要求较高的代码,其中无符号64位整数(ulong
)的乘法是一个瓶颈。
.NET Core 3.0 带来了硬件内部函数的支持,这是非常棒的,它们可以通过 System.Runtime.Intrinsics
命名空间访问。
我目前使用的是可移植实现,返回128位结果的高位和低位的元组:
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static unsafe (ulong Hi, ulong Lo) Multiply64(ulong x, ulong y)
{
ulong hi;
ulong lo;
lo = x * y;
ulong x0 = (uint)x;
ulong x1 = x >> 32;
ulong y0 = (uint)y;
ulong y1 = y >> 32;
ulong p11 = x1 * y1;
ulong p01 = x0 * y1;
ulong p10 = x1 * y0;
ulong p00 = x0 * y0;
// 64-bit product + two 32-bit values
ulong middle = p10 + (p00 >> 32) + (uint)p01;
// 64-bit product + two 32-bit values
hi = p11 + (middle >> 32) + (p01 >> 32);
return (hi, lo);
}
我希望使用指令集优化来提升速度。当有BMI2指令集时,我知道如何使用它(比可移植版本快50%):
ulong lo;
ulong hi = System.Runtime.Intrinsics.X86.Bmi2.X64.MultiplyNoFlags(x, y, &lo);
return (hi, lo);
我完全不知道如何使用其他可用的内在函数;它们似乎都依赖于Vector<128>
类型,而且似乎没有一个处理ulong
类型的。
我该如何使用SSE、AVX等来实现ulong
的乘法?
Vector<ulong>
怎么样?可以使用 System.Numerics.Vectors。但是似乎使用乘法的 ulong 没有任何优势。 - Jeroen van Langenulong
一起使用,例如Sse2.Multiply
。 - Cocowalla