我目前正在考虑移植我的metro哈希实现以使用C#7功能,因为有些部分可能会从ref本地人那里获益以提高性能.哈希在ulong[4]
数组上进行计算,但结果是16个byte
数组.目前我正在将ulong
数组复制到结果byte
缓冲区,但这需要一些时间.所以我想知道在System.Runtime.CompilerServices.Unsafe
这里使用是否安全:
var result = new byte[16];
ulong[] state = Unsafe.As<byte[], ulong[]>(ref result);
ref var firstState = ref state[0];
ref var secondState = ref state[1];
ulong thirdState = 0;
ulong fourthState = 0;
Run Code Online (Sandbox Code Playgroud)
上面的代码片段意味着我也使用结果缓冲区来进行状态计算的部分,而不仅仅是最终输出.
我的单元测试是成功的,并且根据benchmarkdotnet跳过块复制将导致20%的性能提升,这足以让我发现它是否正确使用它.
以当前的.NET术语,这将非常适合Span<T>
:
Span<byte> result = new byte[16];
Span<ulong> state = MemoryMarshal.Cast<byte, ulong>(result);
Run Code Online (Sandbox Code Playgroud)
这将强制执行长度等操作,同时具有良好的JIT行为且不需要unsafe
。您甚至可以stackalloc
使用原始缓冲区(从C#7.2起):
Span<byte> result = stackalloc byte[16];
Span<ulong> state = MemoryMarshal.Cast<byte, ulong>(result);
Run Code Online (Sandbox Code Playgroud)
请注意Span<T>
长度更改正确;Span<Vector<T>>
如果您想使用SIMD进行硬件加速,将其转换成简单也是很简单的。