Tho*_*ler 0 .net c# optimization hash performance
我想要生成大量 (10 TB) 看似随机但可预测的数字。生成速度应该超过快速SSD,所以我想要3000 MB/s到4000 MB/s。
文件写入后,将再次读取数字并重新生成,以便进行比较。整个程序应该检查磁盘。
目前我正在考虑哈希。为了可预测性,要散列的数据只是一个 8 字节数字 ( ulong)。所以在二进制文件中它看起来像这样
<32 bytes of SHA256(0)> <32 bytes of SHA256(1)> ...
Run Code Online (Sandbox Code Playgroud)
我不认为我可以使用带种子的随机数生成器,因为我无法告诉随机数生成器生成第n个数字。但我可以告诉 SHA256 算法计算 SHA256(n)。
我使用 SHA256 算法对 128 MB 数据进行了测试,如下所示:
Parallel.For(0, 128 * 1024 * 1024 / 32, // 128 MB / length of the hash
a => {
var sha = SHA256.Create();
sha.Initialize();
var ba = new byte[8];
ba[0] = (byte)((long)a >> 0 & 0xFF);
ba[1] = (byte)((long)a >> 8 & 0xFF);
ba[2] = (byte)((long)a >> 16 & 0xFF);
ba[3] = (byte)((long)a >> 24 & 0xFF);
ba[4] = (byte)((long)a >> 32 & 0xFF);
ba[5] = (byte)((long)a >> 40 & 0xFF);
ba[6] = (byte)((long)a >> 48 & 0xFF);
ba[7] = (byte)((long)a >> 56 & 0xFF);
var hash = sha.ComputeHash(ba);
// TODO: aggregate the byte[]s, stream to file
}
);
Run Code Online (Sandbox Code Playgroud)
这样,在运行频率为 4.08 GHz 的 Ryzen 7 2700X 8 核处理器上,吞吐量仅为 95 MB/s。
有机会将其速度加快至 4000 MB/s 吗?
我认为如果不使用 GPU 就不可能达到这个速度。但您可以采取以下一些措施来获得一些性能:
Parallel.For创建 SHA256 对象,以及大小为 8 的字节数组来保存要散列的数据,每个任务一次。Initialize.Unsafe设置所有字节,而不是手动将 long 转换为字节数组,一次一个字节。TryComputeHash代替,ComputeHash因为它允许传递输出的跨度。这是实现上述内容的代码:
Parallel.For(0, 128 * 1024 * 1024 / 32, // 128 MB / length of the hash
() => (SHA256.Create(), new byte[8], new byte[32]),
(a, state, tuple) =>
{
Unsafe.As<byte, long>(ref tuple.Item2[0]) = a;
tuple.Item1.TryComputeHash(tuple.Item2, tuple.Item3, out _);
var hash = tuple.Item3;
// TODO: aggregate the byte[]s, stream to file
return tuple;
},
tuple => tuple.Item1.Dispose()
);
Run Code Online (Sandbox Code Playgroud)