4

好吧,这个问题确实是一个挑战!

背景

我正在从事一个涉及大于正常数字的基于算术的项目。我是新手,我将使用 4 GB 上限文件大小的最坏情况情景(我什至希望将其扩展到 5 GB 上限,因为我之前看到文件大小大于 4 GB - 特别是图像 *. iso 文件)

一般问题

现在,我将应用计算的算法目前并不重要,但加载和处理如此大量的数据 - 数字 - 才是重要的。

  • ASystem.IO.File.ReadAllBytes(String)只能读取 2 GB 的文件数据上限,所以这是我的第一个问题 - 我将如何加载和/或配置访问内存,这样的文件大小 - 两倍,如果不是更多?
  • 接下来,我正在编写自己的类来将“流”或字节数组视为一个大数字,并添加多个运算符方法来执行十六进制算术,直到我System.Numerics.BigInteger()在线阅读该类 - 但是没有BigInteger.MaxValue而且我只能一次最多加载 2 GB 的数据,我不知道它的潜力是什么BigInteger——即使与我正在编写的对象相比Number()(它确实具有我想要的最小潜力)。可用内存和性能也存在问题,尽管我不太关心速度,而是成功地完成了这个实验过程。

概括

  • 我应该如何加载 4-5 GB 的数据?
  • 加载后的数据应该如何存储和处理?坚持BigInteger还是完成我自己的Number课程?
  • 我应该如何在运行时处理如此大量的内存而不会耗尽内存?我将像处理任何其他数字而不是字节数组一样处理 4-5 GB 的数据 - 执行诸如除法和乘法之类的算术运算。

PS 根据保密协议,我不能透露有关该项目的太多信息。;)

对于那些希望从我的 Number 对象中查看每个字节数组加法器(C#)的示例运算符的人:

public static Number operator +(Number n1, Number n2)
{
    // GB5_ARRAY is a cap constant for 5 GB - 5368709120L
    byte[] data = new byte[GB5_ARRAY];
    byte rem = 0x00, bA, bB, rm, dt;
    // Iterate through all bytes until the second to last
    // The last byte is the remainder if any
    // I tested this algorithm on smaller arrays provided by the `BitConverter` class,
    // then I made a few tweeks to satisfy the larger arrays and the Number object
    for (long iDx = 0; iDx <= GB5_ARRAY-1; iDx++)
    {
        // bData is a byte[] with GB5_ARRAY number of bytes
        // Perform a check - solves for unequal (or jagged) arrays
        if (iDx < GB5_ARRAY - 1) { bA = n1.bData[iDx]; bB = n2.bData[iDx]; } else { bA = 0x00; bB = 0x00; }
        Add(bA, bB, rem, out dt, out rm);
        // set data and prepare for the next interval
        rem = rm; data[iDx] = dt;
    }
    return new Number(data);
}
private static void Add(byte a, byte b, byte r, out byte result, out byte remainder)
{
    int i = a + b + r;
    result = (byte)(i % 256); // find the byte amount through modulus arithmetic
    remainder = (byte)((i - result) / 256); // find remainder
}
4

3 回答 3

6

通常,您将使用流式 API 处理大文件,可以是原始二进制文件 ( Stream),也可以通过一些协议阅读器 ( XmlReader,StreamReader等)。在某些情况下,这也可以通过内存映射文件来完成。这里的关键点是您一次只能查看文件的一小部分(一个中等大小的数据缓冲区、逻辑“行”或“节点”等 - 取决于场景)。

奇怪的是,您希望以某种方式将其直接映射到某种形式的大数。坦率地说,如果没有更多信息,我不知道我们如何提供帮助,但如果你正在处理这个大小的实际数字,我认为你会很困难,除非二进制协议使这变得方便。而“进行除法和乘法等算术运算”对原始数据毫无意义;这只对定义了自定义操作的解析数据有意义。

另外:请注意,在 .NET 4.5 中,您可以翻转配置开关以扩展数组的最大大小,超过 2GB 限制。它仍然一个限制,但是:它有点大。不幸的是,最大元素数仍然相同,因此如果您使用byte[]数组,它将无济于事。但是,如果您正在使用SomeCompositeStruct[],您应该能够获得更高的使用率。参见gcAllowVeryLargeObjects

于 2012-09-11T06:38:46.913 回答
3

使用FileStream:http: //msdn.microsoft.com/en-us/library/system.io.filestream.aspx

于 2012-09-11T06:38:05.143 回答
0

FileStream是你的开始。

如果您没有足够的内存(我认为它应该至少是您的最大数字大小的 4 倍),您将需要使用硬盘。因此,您宁愿加载部分数据,进行一些计算并将其写回硬盘,而不是将所有数据都保存在内存中。

于 2012-09-11T06:42:25.023 回答