バルクローバルOCR中のハイピークメモリー
一度に多くのPDFセグメントに対してOCRを実行することはメモリー消費を倍増させます。 各タスクはIronTesseractエンジンが言語モデルファイルを毎回リロードします。フルプロセッサーの同時実行性では、これによりメモリピークが数GB範囲に達し、メモリに制限のある環境でのスパイクが失敗します。
OCRは生来メモリを多く使用します。 すべてのIronTesseractエンジンは言語モデルファイルをメモリーにロードします。 各セグメントごとに新しいエンジンを作成すると、それらのモデルが繰り返しリロードされ、CPUコアごとに1つのOCRタスクを実行すること(Environment.ProcessorCount)により、多くのビットマップヘビージョブが並行して実行されます。アクティブなタスクの制限がまったくないと、ピークメモリは完全に同時実行性に比例して拡大します。
修正方法は、飛行中のジョブの数を制限し: 同時実行性の制限を設定し、プールからエンジンを再利用し、セマフォで作業をゲートします。
解決策
1. OCRの同時実行性を制限します
同時に行うOCRタスクの数を小さな天井にクランプします。 少ない同時タスクは、一度にメモリーにあるフルページビットマップの数が減り、それがピークを直接下げます。 機械の能力に合わせて天井を調整します。
// Clamp concurrency to avoid memory saturation and CPU over-subscription.
int concurrency = Math.Clamp(Environment.ProcessorCount / 2, 1, 4);
2. エンジンをプールします
起動時に同時スロットごとに1つだけIronTesseractエンジンを作成し、それらを各セグメントで再利用する代わりに、毎回新しいエンジンを構築し、言語モデルを再ロードします。
// Pre-create one engine per concurrent slot and reuse them across segments.
var enginePool = new ConcurrentBag<IronTesseract>(
Enumerable.Range(0, concurrency).Select(_ => new IronTesseract())
);
一度プールを構築することで、セグメントごとに支払うのではなく、全体の実行にわたって言語モデルのロードコストを分割します。
3. セマフォで作業をゲートします
同時実行の制限にusingでラップします。 各タスクは開始前にRelease()を呼び出し、許可された数のセグメントだけが一度に飛行中になります。
using var semaphore = new SemaphoreSlim(concurrency);
await semaphore.WaitAsync();
try
{
// Rent a pre-loaded engine from the pool.
if (!enginePool.TryTake(out var ocr))
ocr = new IronTesseract(); // Defensive fallback; should never be reached.
try
{
using var input = new OcrInput();
input.LoadPdf(segmentStream); // page-range segment produced upstream
var ocrResult = await ocr.ReadAsync(input);
ocrResult.SaveAsSearchablePdf(outputPath);
}
finally
{
enginePool.Add(ocr); // Return engine to pool for the next waiting segment.
}
}
finally
{
semaphore.Release();
}
finallyにエンジンを戻すことで、事前ロードされたエンジンが次の待機中セグメントに直接渡されます。
4. 各セグメントごとにOcrInputを破棄します
各usingでラップして、そのセグメントが読み取られるとすぐにそのレンダードページビットマップが解放され、次のタスクがスロットを獲得する前に解放されます。
using の OcrInput です; それなしでは、解放されたスロットもページビットマップを保持します。
Curtis Chauは、カールトン大学でコンピュータサイエンスの学士号を取得し、Node.js、TypeScript、JavaScript、およびReactに精通したフロントエンド開発を専門としています。直感的で美しいユーザーインターフェースを作成することに情熱を持ち、Curtisは現代のフレームワークを用いた開発や、構造の良い視覚的に魅力的なマニュアルの作成を楽しんでいます。