我有这个代码
//N = 32;
//B = 27;
using (FileStream fs = File.Open(path, FileMode.OpenOrCreate, FileAccess.ReadWrite))
{
using (BinaryReader br = new BinaryReader(fs))
{
using (BinaryWriter bw = new BinaryWriter(fs))
{
for (int k = B; k < N; ++k)
{
Console.WriteLine(k);
long pt = 0;
long j = 1L << k;
for (long i = 0; i < (1L << (N - 1)); ++i)
{
long b1;
long b2;
br.BaseStream.Seek(8 * (pt), SeekOrigin.Begin);
b1 = br.ReadInt64();
br.BaseStream.Seek(8 * (j - 1), SeekOrigin.Current);
b2 = br.ReadInt64();
long t1 = b1 + b2;
long t2 = b1 - b2;
bw.BaseStream.Seek(8 * (pt), SeekOrigin.Begin);
bw.Write(t1);
bw.BaseStream.Seek(8 * (j - 1), SeekOrigin.Current);
bw.Write(t2);
pt += 1;
if ((pt & (j - 1L)) == 0)
{
pt += j;
}
if ((i % 100000) == 0) Console.WriteLine(i);
}
}
}
}
}
发生的事情是,该程序从一个很大的(17 GB)文件中的不同位置读取两个long,然后将它们相加/相减,然后在相同位置重写新值。
据我所知,读取数据的最有效方法是将大块读入缓冲区,然后使用该缓冲区。但是,这种方法在这里行不通,因为基于 pt 和 j 的值,它可能是从文件的开头和结尾读取的,当然我无法将所有17 GB的内存都存储在内存中。
行
if ((i % 100000) == 0) Console.WriteLine(i);
用于调试,在我的计算机上它们之间大约需要2秒钟。我需要这个要快得多。我关注的论文说,在此循环中,它们的实现花费了不到30分钟的时间。有没有更快的选择可以快速读取大量数字数据?
答案 0 :(得分:2)
这本身并不是一个答案。但是,它应该给您一些思路,让您知道如何具体地加快速度
乍一看,这可分为概率,并行度和卡盘大小。
如果很有可能在较大的块中找到下一个/写入的读取,则较大的块大小将提高性能。反过来,它也不必继续扫描磁盘。
如果您使用的是 SSD ,则可能会以比可能使用的默认4k块更高的性能(一次)加载Mb级。
此外,似乎可以将其分解为并行工作负载...虽然目前尚不清楚一开始需要进行哪些修改。
但是,如果您真的想要这么快
如果您可以这样做(这是推测性的),则可能可以更快地加快许多因素的速度。而且要花费数百美元的内存和一天的编码时间。
很棒的评论来自 @NPras
除了自己管理RAM缓存/分块外,您还可以 想看一下memory-mapped file的概念,并让操作系统 为您管理
答案 1 :(得分:0)
如果我理解正确,那么结果将写回到您刚刚读取的位置。
因此,如果您颠倒写入顺序,则第一次写入将是您最后一次读取的位置。
这将减少寻道时间。
此外,这意味着下一个读取也将与另一个写入相邻,从而再次减少了查找时间。
现在,“ i”上的主循环显然很长,但我认为您可以: