docling-project / docling-project/docling

Use it or not use it GPU with OCR

Open
#2,727 6 comments 0 reactions 0 assignees View on GitHub
question
Dominant language
Python
Stars
66.4k
Forks
4.8k
Avg merge
2d 21h
Merged PRs (30d)
84

Description

### Question
First of all, thank you for the library — the results are fantastic. However, we’re running more “real-world” tests and benchmarking with and without GPU, and we’re finding that there’s no difference between enabling or disabling the GPU.

Using EasyOCR and enabling the accelerators, we don’t see any time differences, and we also don’t see GPU usage increase. In addition, we see that the processing time seems to get stuck on the OCR timing.

Testing with RapidOCR, we observe the same behavior. We see sporadic GPU usage around 1% or occasional spikes, but there’s no sustained/intensive GPU usage. The processing times are the same when using CPU vs GPU.

Below we’re sharing the test code:

We’re also including the requirements.

We’ve tested both locally and in Colab with GPU (T4).

We honestly don’t know why the GPU isn’t being used (configuration, environment variables, etc.).

The results look great, but the response times should also be in line with GPU expectations.
...

### code to replicate (notebook colab)
```python
!uv pip install docling matplotlib pillow pandas python-dotenv easyocr
```

```python
# python
import logging
from logging.handlers import RotatingFileHandler
import sys

# Formatter
fmt = "%(asctime)s %(levelname)s [%(name)s] %(message)s"
formatter = logging.Formatter(fmt)

# Console handler
sh = logging.StreamHandler(sys.stdout)
sh.setFormatter(formatter)

# Rotating file handler
fh = RotatingFileHandler("docling.log", maxBytes=10_000_000, backupCount=5, encoding="utf-8")
fh.setFormatter(formatter)

# Root logger
root = logging.getLogger()
root.setLevel(logging.DEBUG)
root.handlers[:] = [] # limpiar handlers si existieran
root.addHandler(sh)
root.addHandler(fh)

# Forzar DEBUG en loggers específicos
for name in ("docling", "rapidocr", "onnxruntime", "paddle", "tesseract"):
logging.getLogger(name).setLevel(logging.DEBUG)
```

```python
from docling.datamodel.settings import settings
import torch
from docling.datamodel.pipeline_options import EasyOcrOptions
from docling.datamodel.accelerator_options import AcceleratorOptions, AcceleratorDevice
from pathlib import Path
# Core Docling imports
from docling.document_converter import DocumentConverter
from docling.datamodel.base_models import InputFormat
from docling.datamodel.pipeline_options import PdfPipelineOptions
from docling.document_converter import PdfFormatOption
use_gpu = torch.cuda.is_available()
image_scale=2
settings.debug.profile_pipeline_timings = True

image_scale=2
converter_pdf__easyocr = DocumentConverter(
format_options={
InputFormat.PDF: PdfFormatOption(
pipeline_options=PdfPipelineOptions(
do_ocr=True, image_scale=image_scale,
generate_page_images=True,
generate_picture_images=True,
ocr_options=EasyOcrOptions(force_full_page_ocr=True, use_gpu=True),
accelerator_options=AcceleratorOptions(device=AcceleratorDevice.CUDA)
)
)
}
)

# Convertir un documento
result = converter_pdf__easyocr.convert(docling_paper)
doc = result.document
# Exportar a Markdown
md_out = doc.export_to_markdown()
# Imprimir un extracto del resultado
print(f"{md_out}")
```

```python
result.timings
```
```
{'pipeline_total': ProfilingItem(scope=, count=1, times=[62.96464266599992], start_timestamps=[datetime.datetime(2025, 12, 5, 8, 38, 3, 480321)]),
'page_parse': ProfilingItem(scope=, count=8, times=[0.5054820290000634, 0.18391264199999569, 0.13429985400000533, 0.13457061500002965, 0.3045847070000036, 0.1251547939999682, 0.15417373699995096, 0.09638401299991983], start_timestamps=[datetime.datetime(2025, 12, 5, 8, 38, 3, 486682), datetime.datetime(2025, 12, 5, 8, 38, 4, 1119), datetime.datetime(2025, 12, 5, 8, 38, 4, 187343), datetime.datetime(2025, 12, 5, 8, 38, 4, 323589), datetime.datetime(2025, 12, 5, 8, 38, 4, 471082), datetime.datetime(2025, 12, 5, 8, 38, 4, 991496), datetime.datetime(2025, 12, 5, 8, 38, 5, 125172), datetime.datetime(2025, 12, 5, 8, 38, 5, 281881)]),
'ocr': ProfilingItem(scope=, count=8, times=[8.76018142099997, 5.947348726999962, 9.09631627500005, 9.11614105000001, 5.167917539999962, 10.212629470000024, 4.786586475999911, 8.558953165000048], start_timestamps=[datetime.datetime(2025, 12, 5, 8, 38, 3, 992345), datetime.datetime(2025, 12, 5, 8, 38, 12, 752720), datetime.datetime(2025, 12, 5, 8, 38, 18, 700102), datetime.datetime(2025, 12, 5, 8, 38, 27, 796446), datetime.datetime(2025, 12, 5, 8, 38, 36, 912614), datetime.datetime(2025, 12, 5, 8, 38, 42, 80702), datetime.datetime(2025, 12, 5, 8, 38, 52, 293364), datetime.datetime(2025, 12, 5, 8, 38, 57, 79968)]),
'layout': ProfilingItem(scope=, count=3, times=[0.11270990999992136, 0.2865554349999684, 0.1954698819999976], start_timestamps=[datetime.datetime(2025, 12, 5, 8, 38, 12, 752875), datetime.datetime(2025, 12, 5, 8, 38, 42, 80859), datetime.datetime(2025, 12, 5, 8, 39, 5, 640249)]),
'table_structure': ProfilingItem(scope=, count=8, times=[4.90999999556152e-05, 5.7989999959318084e-05, 1.9873999917763285e-05, 1.6474000062771665e-05, 0.4818315159999429, 8.239499993578647e-05, 1.924000002873072e-05, 2.0193999944240204e-05], start_timestamps=[datetime.datetime(2025, 12, 5, 8, 38, 12, 922935), datetime.datetime(2025, 12, 5, 8, 38, 42, 555499), datetime.datetime(2025, 12, 5, 8, 38, 42, 555548), datetime.datetime(2025, 12, 5, 8, 38, 42, 555574), datetime.datetime(2025, 12, 5, 8, 38, 42, 555597), datetime.datetime(2025, 12, 5, 8, 39, 5, 944074), datetime.datetime(2025, 12, 5, 8, 39, 5, 944126), datetime.datetime(2025, 12, 5, 8, 39, 5, 944150)]),
'page_assemble': ProfilingItem(scope=, count=8, times=[0.0005914640000810323, 0.000582733999976881, 0.000677192000011928, 0.0006095479999430609, 0.00028568799996264715, 0.00040288900004270545, 0.00021934200003670412, 0.00037494000002880057], start_timestamps=[datetime.datetime(2025, 12, 5, 8, 38, 12, 923054), datetime.datetime(2025, 12, 5, 8, 38, 43, 37742), datetime.datetime(2025, 12, 5, 8, 38, 43, 39444), datetime.datetime(2025, 12, 5, 8, 38, 43, 41614), datetime.datetime(2025, 12, 5, 8, 38, 43, 43865), datetime.datetime(2025, 12, 5, 8, 39, 5, 944530), datetime.datetime(2025, 12, 5, 8, 39, 5, 946195), datetime.datetime(2025, 12, 5, 8, 39, 5, 948045)]),
'doc_assemble': ProfilingItem(scope=, count=1, times=[0.49385646299992914], start_timestamps=[datetime.datetime(2025, 12, 5, 8, 39, 5, 949561)]),
'reading_order': ProfilingItem(scope=, count=1, times=[0.0372448529999474], start_timestamps=[datetime.datetime(2025, 12, 5, 8, 39, 5, 949646)]),
'doc_enrich': ProfilingItem(scope=, count=1, times=[0.001482441000007384], start_timestamps=[datetime.datetime(2025, 12, 5, 8, 39, 6, 443468)])}
```
### Results:
62 seconds - 8pages - ocr 58secs with GPU

### GPU - usage
0.1 (init with 3.8 and finish with 3.9)
Image

Other test local with CUDA happens the same.

### requirements
+ colorlog==6.10.1
+ docling==2.64.0
+ docling-core==2.54.0
+ docling-ibm-models==3.10.3
+ docling-parse==4.7.2
+ easyocr==1.7.2
+ faker==38.2.0
+ filetype==1.2.0
+ jsonlines==4.0.0
+ jsonref==1.1.0
+ latex2mathml==3.78.1
+ marko==2.2.1
+ mpire==2.10.2
+ ninja==1.13.0
+ polyfactory==3.1.0
+ pyclipper==1.4.0
+ pylatexenc==2.10
+ pypdfium2==4.30.0
+ python-bidi==0.6.7
+ python-docx==1.2.0
+ python-pptx==1.0.2
+ rapidocr==3.4.2
+ semchunk==2.2.2
+ tree-sitter==0.25.2
+ tree-sitter-c==0.24.1
+ tree-sitter-java==0.23.5
+ tree-sitter-javascript==0.25.0
+ tree-sitter-python==0.25.0
+ tree-sitter-typescript==0.23.2
- typer==0.20.0
+ typer==0.19.2
+ xlsxwriter==3.2.9

TANKS

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.