需要4 GB或5 GB数字的算法 - 是否可能?

时间:2012-09-11 06:33:49

标签: c# memory biginteger

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

背景

我正在研究一个涉及大于正常数字的基于算术的项目。我是新的,我将使用4 GB封装文件大小的最坏情况 - (我正在跳跃甚至将其扩展到5GB上限,因为我之前看到的文件大小超过4 GB - 特别是图像*。 iso文件)

一般问题

现在,我将应用计算的算法此刻无关紧要,但加载和处理如此大量的数据 - 数字 - 可以。

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

摘要

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

根据非披露协议,我无法透露有关该项目的太多信息。 ;)

对于那些希望从我的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
}

3 个答案:

答案 0 :(得分:6)

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

这个奇怪的地方是你想要以某种方式直接映射到某种形式的大数字。坦率地说,我不知道在没有更多信息的情况下我们如何能够提供帮助,但如果你正在处理这个大小的实际数量,我认为除非二进制协议使得你要努力那方便。并且“执行诸如除法和乘法之类的算术”对于原始数据是没有意义的;只有定义了自定义操作的解析数据才有意义。

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

答案 1 :(得分:3)

答案 2 :(得分:0)

FileStream是你的开始。

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