わかりました、この問題は確かに挑戦です!
バックグラウンド
私は、通常よりも大きな数値を含む算術ベースのプロジェクトに取り組んでいます。私は、4 GB を上限とするファイル サイズの最悪のシナリオで作業するつもりでした (以前に 4 GB を超えるファイル サイズを見たことがあるので、それを 5 GB の上限に拡張することさえ望んでいました - 具体的には画像 *. isoファイル)
一般的な質問
さて、計算を適用するアルゴリズムは現時点では問題ではありませんが、そのような大量のデータ (数値) の読み込みと処理は重要です。
- A
System.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
}