4

わかりました、この問題は確かに挑戦です!

バックグラウンド

私は、通常よりも大きな数値を含む算術ベースのプロジェクトに取り組んでいます。私は、4 GB を上限とするファイル サイズの最悪のシナリオで作業するつもりでした (以前に 4 GB を超えるファイル サイズを見たことがあるので、それを 5 GB の上限に拡張することさえ望んでいました - 具体的には画像 *. isoファイル)

一般的な質問

さて、計算を適用するアルゴリズムは現時点では問題ではありませんが、そのような大量のデータ (数値) の読み込みと処理は重要です。

  • ASystem.IO.File.ReadAllBytes(String)は上限の 2 GB 相当のファイル データしか読み取ることができないため、これが最初の問題です。たとえば、ファイル サイズなどのメモリにアクセスするための読み込みや構成を行うにはどうすればよいでしょうか。
  • System.Numerics.BigInteger()次に、「ストリーム」またはバイトの配列を大きな数として扱い、複数の演算子メソッドを追加して、クラスについてオンラインで読むまで、独自のクラスを作成していましたが、クラスがなくBigInteger.MaxValue、私ができるのは一度に最大 2 GB のデータをロードしますが、その可能性がどうなるかわかりませんBigInteger- 私が書いていたオブジェクトと比較してもNumber()(これは私の希望する最小可能性を持っています)。使用可能なメモリとパフォーマンスにも問題がありましたが、速度はあまり気にしませんが、この実験プロセスを正常に完了しました。

概要

  • 4 ~ 5 ギガバイトのデータをロードするにはどうすればよいですか?
  • ロードされたデータをどのように保存および処理すればよいですか? BigInteger自分のNumberクラスを続けるか、それとも終了しますか?
  • メモリを使い果たすことなく、実行時にこのような大量のメモリを処理するにはどうすればよいですか? 4 ~ 5 GB のデータをバイト配列ではなく、他の数値と同様に扱い、除算や乗算などの演算を実行します。

PS 秘密保持契約の下で、このプロジェクトに関する多くの情報を明らかにすることはできません。;)

バイトごとの配列加算器 (C#) の Number オブジェクトからのサンプル演算子を見たい人のために:

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

通常、未加工のバイナリ ( Stream) または何らかのプロトコル リーダー ( 、 など) を介してXmlReaderStreamReaderストリーミング API を使用して大きなファイルを処理します。これは、場合によってはメモリ マップト ファイルを介して行うこともできます。ここで重要な点は、一度にファイルの小さな部分 (適度なサイズのデータ​​ バッファー、論理的な「行」、または「ノード」など - シナリオに応じて) のみを確認することです。

これが奇妙になるのは、これをなんらかの形式の大きな数に直接マップしたいというあなたの願望です。率直に言って、これ以上の情報がなければどうすればよいかわかりませんが、このサイズの実際の数を扱っている場合は、バイナリ プロトコルがそれを便利にしない限り、苦戦することになると思います。また、「除算や乗算などの演算を実行する」ことは、生データでは意味がありません。これは、カスタム操作が定義された解析済みデータでのみ意味があります。

また、.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 is the beginning for you.

If you don't have enough memory (it should be at least 4x more than max your number size I think) you will need to use hard disk. So instead having all data in memory you would rather load part of data, do some computing and write it back to hard disk.

于 2012-09-11T06:42:25.023 に答える