Toplu OCR Sırasında Yüksek Tepe Belleği

This article was translated from English: Does it need improvement?
Translated
View the article in English

Birçok PDF segmenti üzerinde OCR çalıştırmak, bellek kullanımını katlar. Her görev, OcrInput aracılığıyla tam sayfa bit eşlemlerini işler ve her segment için yeni bir IronTesseract motoru, dil modeli dosyalarını her seferinde yeniden yükler. Tam işlemci eşzamanlılığı ile bu, bellek sınırlı ortamlarda arızalanan pik bellek kullanımı ile çoklu GB aralığına itmektedir.

OCR, doğası gereği bellek ağırlıklıdır. Her OcrInput tam sayfa bit eşlemlerini işler ve her IronTesseract motoru dil modeli dosyalarını belleğe yükler. Her segment için yeni bir motor oluşturarak bu modelleri tekrar tekrar yeniden yüklemiş oluruz ve işlemci çekirdeği başına bir OCR görevini (Environment.ProcessorCount) çalıştırmak birçok bit eşlem ağırlıklı işin yan yana çalışmasına olanak tanır. Aktif görev sayısını sınırlayan bir şey olmadığında, pik bellek kullanımı doğrudan eşzamanlılıkla ölçeklenir.

Çözüm, uçuş halindeki iş sayısını sınırlamaktır: eşzamanlılığı sınırlayın, bir havuzdan motorları yeniden kullanın ve çalışmayı bir semaforla yönetin.

Çözüm

1. OCR eşzamanlılığını sınırla

Eşzamanlı OCR görevlerinin sayısını küçük bir tavana sabitleyin. Daha az eşzamanlı görev, bellekte aynı anda daha az tam sayfa resim demektir, bu doğrudan zirve düşer. Tavanı makinenin kapasitesine göre ayarlayın.

// Clamp concurrency to avoid memory saturation and CPU over-subscription.
int concurrency = Math.Clamp(Environment.ProcessorCount / 2, 1, 4);
// Clamp concurrency to avoid memory saturation and CPU over-subscription.
int concurrency = Math.Clamp(Environment.ProcessorCount / 2, 1, 4);
Imports System

' Clamp concurrency to avoid memory saturation and CPU over-subscription.
Dim concurrency As Integer = Math.Clamp(Environment.ProcessorCount \ 2, 1, 4)
$vbLabelText   $csharpLabel

2. Motorları havuz oluştur

Başlangıçta her eşzamanlı yuva için tam olarak bir IronTesseract motoru oluşturun ve dil modelini her seferinde yeni bir motor oluşturmaktan ve yeniden yüklemektense her segmentte bunları yeniden kullanın.

// Pre-create one engine per concurrent slot and reuse them across segments.
var enginePool = new ConcurrentBag<IronTesseract>(
    Enumerable.Range(0, concurrency).Select(_ => new 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())
);
' Pre-create one engine per concurrent slot and reuse them across segments.
Dim enginePool As New ConcurrentBag(Of IronTesseract)(
    Enumerable.Range(0, concurrency).Select(Function(_) New IronTesseract())
)
$vbLabelText   $csharpLabel

Havuzu bir kez oluşturmak, dil-model yükleme maliyetini tüm çalışmaya yayar, segment başına ödeme yapmak yerine.

3. Çalışmayı bir semaforla sınırla

Eşzamanlılık sınırına bir SemaphoreSlim başlatın ve onu using içinde sarın. Her görev başlamadan önce WaitAsync() çağrısı yapar ve Release() bir finally içinde yürütülür, böylece yalnızca izin verilen segment sayısı aynı anda işlenir.

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();
}
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();
}
Imports System.Threading
Imports IronOcr

Dim semaphore As New SemaphoreSlim(concurrency)
Await semaphore.WaitAsync()
Try
    ' Rent a pre-loaded engine from the pool.
    Dim ocr As IronTesseract = Nothing
    If Not enginePool.TryTake(ocr) Then
        ocr = New IronTesseract() ' Defensive fallback; should never be reached.
    End If
    Try
        Using input As New OcrInput()
            input.LoadPdf(segmentStream) ' page-range segment produced upstream
            Dim ocrResult = Await ocr.ReadAsync(input)
            ocrResult.SaveAsSearchablePdf(outputPath)
        End Using
    Finally
        enginePool.Add(ocr) ' Return engine to pool for the next waiting segment.
    End Try
Finally
    semaphore.Release()
End Try
$vbLabelText   $csharpLabel

WaitAsync() çağrısı bir yuva açılana kadar bloke eder ve motora iç finally içinde dönerken bir önceden yüklenmiş motoru doğrudan bekleyen bir sonraki segmente teslim eder.

4. Her segment için OcrInput'u elden çıkarın

Her OcrInput, çalıştırılan sayfa bit eşlemlerinin okuyucu segmentten önce, sonraki görev yuva talebinde bulunmadan serbest bırakılmasını sağlamak için using ile sarılır.

İpuçlarıusing üzerindeki OcrInput, bit eşlem belleğini segmentler arasında birikmesini önleyen şeydir. olmadan, serbest bırakılan yuvalar hala sayfa bit eşlemelerini tutar.

Curtis Chau
Teknik Yazar

Curtis Chau, Bilgisayar Bilimleri alanında Lisans Derecesine (Carleton Üniversitesi) sahip ve Node.js, TypeScript, JavaScript ve React konularında uzmanlaşmış ön uç geliştirmeyle ilgileniyor. Sezgisel ve estetik açıdan hoş kullanıcı arayüzleri oluşturma tutkunu, Curtis modern çerçevelerle çalışmayı ve iyi yapı...

Daha Fazla Oku
Başlamaya Hazır mısınız?
Nuget İndirmeler 6,136,090 | Sürüm: 2026.7 yeni yayınlandı
Still Scrolling Icon

Hâlâ Kaydırıyor Musunuz?

Hızlıca kanıt ister misiniz? PM > Install-Package IronOcr
örnek çalıştır görüntünüzün aranabilir metin haline gelmesini izleyin.