基本上,在 ABBYY FineReader Engine 中使用多进程处理主要有三种方式:
一方面,您可以使用一个 Engine 对象,并将 Engine 对象的 MultiProcessingParams 属性设置为适当的值。
ABBYY FineReader Engine 支持两种不同的对象,可通过单个 Engine 实例实现多进程处理。它们分别是 FRDocument 对象 (请参见使用 FRDocument 对象进行处理) 和 BatchProcessor 对象 (请参见使用 Batch Processor 进行处理) 。
另一方面,您可以借助 COM 将多个 Engine 实例加载为进程外服务器 (使用 OutprocLoader 对象) ,并在各自的进程中使用这些实例。请参见使用 Engine 池进行处理。
请注意,并行处理比顺序处理需要更多内存。对于工作站,一般建议配置为 350 MB * (核心数) + 450 MB RAM;如果您处理的是阿拉伯语或 CJK 语言 文档,则建议配置为 850 MB * (核心数) + 750 MB RAM。
我们先假定您要处理大量文档。但与此同时,还必须考虑您需要获得什么样的结果,并选择最适合完成任务的方法。需要考虑的典型场景如下:
- 转换页数较多的多页文档。这通常意味着处理书籍、长篇报告等。在这种情况下,您可以并行识别文档各页,然后在主进程中执行合成,再并行导出。如果使用 Engine 池,您还可以同时处理多个多页文档,但内存消耗可能会非常大,甚至导致“内存不足”错误。
- 转换大量单页文档。这种情况常见于处理发票、合同、信函等。对于这种场景,并行处理最为简单,因为单页文档彼此独立,也不需要同时占用大量内存。
- 处理大量图像,并从中搜索所需信息,或以其他方式使用识别结果。您可能并不需要将其中大多数转换为可编辑格式,因此合成和导出的速度并不是问题。在这种情况下,需要在多个进程中执行的操作是遍历版面块并访问文本块的识别结果。
如果您希望在导出时使用并行处理,请注意,此功能仅支持导出为 PDF (TextOnly 模式除外) 和 PPTX 格式。
-
对于多页文档的并行处理,我们推荐使用 FRDocument。这是编码最简单的一种多处理方式,因为您无需实现任何额外接口。
打开、预处理、分析和识别会并行执行;文档合成则在主进程中顺序执行,随后导出到 PDF (TextOnly 模式除外) 和 PPTX 格式会并行执行。
-
要处理从某个来源 (例如扫描仪) 接收的众多单页文档,我们推荐使用 BatchProcessor。
这种方法的优势在于,即使您事先不知道文档的数量、文档类型可能各不相同,并且必须在文档到达时立即进行处理,也可以使用它。缺点是实现工作量较大:您需要实现文件适配器和自定义图像源的接口。
所有处理阶段均并行执行,因为对于单页文档,页面合成和文档合成会针对每个页面单独执行。
在使用 Batch Processor 的场景中,不支持并行导出。
-
要并行执行众多单页文档的完整处理,您可以使用通过 COM 加载的进程外 Engine 池。这种方法速度最高效,并能自动消除所有多线程相关难题:所有与 ABBYY FineReader Engine 对象相关的操作均通过 COM 进行序列化。但它有一些限制:
-
由于使用 COM,您需要注册 FREngine.dll;
-
如果您的代码使用 C++ 编写,与 COM 的交互需要比 C# 更多的例行编码;
-
在这种情况下,处理在另一个进程中进行,因此无法从内存打开图像,而且迭代识别结果需要更多时间,因为每个请求都必须传递到另一个进程并返回;
-
最后,加载多个 Engine 实例会增加内存消耗,尤其是所有处理阶段并行执行时,多个合成操作可能同时进行,从而进一步消耗更多内存。
-
要捕获并处理并行处理期间发生的事件,您可以使用 IParallelProcessingCallback 接口。此接口对于处理问题情况非常有用。例如,当发生超时错误时,IParallelProcessingCallback 接口可根据用户偏好提供多种解决方案。有关更多信息,请参阅 IParallelProcessingCallback::OnWaitIntervalExceeded。
页面并行处理期间发生的事件会转换为整个文档的事件。
下表呈现了性能测试的结果。
| <br /> | 单页文档 | 一个多页文档 | 不导出结果,仅搜索结果 |
|---|
| 顺序处理 | 60 | 51 | 87 |
| 使用 FRDocument 处理 | 41 | 117 | 57 |
| 使用 FRDocument 处理 (使用 PageFlushingPolicy = PFP_KeepInMemory) | 55 | 141 | 82 |
| 使用 Batch Processor 处理 | 99 | 115 | 294 |
| 使用 Engine 池处理 | 165 | 10 | 102 |
测试机器的处理器为 Intel® Core™ i5-4440 (3.10 GHz,4 个物理核心) ,8 GB 内存,同时运行的进程数为 4。在 300 张英文图像上进行了性能测试,使用 DocumentArchiving_Speed 预定义配置文件。表中的数字表示每分钟处理的页面数。在“单页文档”和“一个多页文档”场景中,文档被导出为 PDF 格式。
要运行的进程数会根据可用的物理或逻辑 CPU 核心数、许可证中可用的空闲 CPU 核心数以及文档页数自动确定。要启用多进程模式,请按以下步骤操作:
- 设置 Engine 对象的 MultiProcessingParams 子对象中 MultiProcessingMode 属性的值。如果此属性设置为 MPM_Parallel 或 MPM_Auto,且文档页数和可用 CPU 核心数均大于 1,则会使用并行处理。
- 使用 RecognitionProcessesCount 属性调整要运行的进程数,并根据需要指定其他属性的值。
配置好多进程设置后,您可以按标准流程使用 FRDocument。当您调用 FRDocument 对象的以下任一方法时,ABBYY FineReader Engine 会自动启动多个识别进程:
- AddImageFile, AddImageFileFromMemory, AddImageFileFromStream, AddImageFileWithPassword, AddImageFileWithPasswordCallback
- Preprocess, PreprocessPages
- Analyze, AnalyzePages
- Recognize, RecognizePages
- Process, ProcessPages
- Export, ExportPages, ExportToMemory — 仅适用于导出为 PDF (TextOnly 模式除外) 和 PPTX 格式
系统会为文档中的每一页创建一个新的处理任务,并将该任务分配给某个识别进程。识别进程完成当前任务后,会接收下一个处理任务。此过程会持续进行,直到所有任务均处理完毕。
// 创建文档
FREngine.IFRDocument document = engine.CreateFRDocument();
// 向文档添加页面
for( int index = 0; index < filesNumber; index++ ) {
string imagePath = filePaths[index];
document.AddImageFile( imagePath, null, null );
}
// 设置多进程参数
engine.MultiProcessingParams.MultiProcessingMode = FREngine.MultiProcessingModeEnum.MPM_Parallel;
engine.MultiProcessingParams.RecognitionProcessesCount = coresNumber;
// 创建并设置文档处理参数
FREngine.IDocumentProcessingParams documentProcessingParams = engine.CreateDocumentProcessingParams();
...
// 处理文档
document.Process( documentProcessingParams );
// 像往常一样合成并导出文档,处理结果等
...
ABBYY FineReader Engine 发行包中包含 MultiProcessingRecognition 演示工具。该工具展示了结合 FRDocument 对象使用多进程识别所带来的速度提升,并提供了一个实现示例,您可以在此基础上开始开发自己的应用程序。
初始化 Batch Processor 时,会调用并配置异步识别进程。随后,处理器会从自定义图像源获取图像文件。对于图像文件中的每个页面,都会创建一个新的处理任务,并将该任务分配给某个识别进程。如果某个文件的所有任务都已提交处理,但并非所有识别进程都处于忙碌状态,则会从源的图像队列中取出下一个图像文件并提交处理。此过程会持续进行,直到第一个图像页面被转换并返回给用户。返回给用户的页面顺序,与它们从图像源中取出的顺序一致。
要使用 Batch Processor 组织多进程处理,请执行以下操作:
- 实现 IImageSource 和 IFileAdapter 接口,以提供对图像源及其中图像文件的访问。
- [可选] 实现 IAsyncProcessingCallback 接口来管理处理过程。该接口的方法允许你处理错误和/或取消处理。
- [可选] 使用 Engine 对象的 MultiProcessingParams 子对象设置多进程。请注意,无需设置 MultiProcessingMode 属性,因为如果使用 Batch Processor,默认会采用并行处理。如有需要,可使用 RecognitionProcessesCount 属性调整要运行的进程数量,并指定其他属性的值。
- 调用 Engine 对象的 CreateBatchProcessor 方法,以获取 BatchProcessor 对象。
- 调用此对象的 Start 方法来初始化处理器并启动异步识别进程。你可以在调用此方法时指定图像源,并传入 IAsyncProcessingCallback 接口和参数对象的引用。
- 在循环中调用 GetNextProcessedPage 方法,直到该方法返回 0,这表示源中已没有更多图像,并且所有已处理图像都已返回给用户。
GetNextProcessedPage 方法返回的页面会一直存在到下一次调用该方法为止。因此,如果你想保存该页面,你必须在下一次调用 GetNextProcessedPage 方法之前,使用 FRPage 对象的方法保存它,或使用 IFRDocument::AddPage 方法将其添加到现有文档中。
// 创建 Batch Processor
FREngine.IBatchProcessor batchProcessor = engine.CreateBatchProcessor();
// 设置多进程参数
engine.MultiProcessingParams.RecognitionProcessesCount = coresNumber;
// 初始化处理器
FREngine.IImageSource imageSource = new CImageSource; // 该类由用户实现
batchProcessor.Start( imageSource, null, null, null );
// 开始处理
while( true ) {
FREngine.IFRPage page = batchProcessor.GetNextProcessedPage();
if( page == null ) {
break; // 没有更多页面了,工作结束
}
// 对页面执行某些操作
page.Synthesize( null );
page.Export("D:\\sample.pdf", FREngine.FileExportFormatEnum.FEF_PDF, null);
}
ABBYY FineReader Engine 发行包包含 BatchProcessing 示例,展示了如何使用 Batch Processor;还包含 BatchProcessingRecognition 演示工具,展示了使用 Batch Processor 进行多进程识别时的速度提升。
在这种多进程场景中,您需要使用多个以进程外方式加载的 Engine 实例。在每个工作线程中,处理过程几乎可以与单线程处理时相同。不过,建议您实现一个自定义图像源,借助某种同步对象在线程之间分配图像,以确保每张图像都只被处理一次。
要以进程外方式加载 Engine 对象,请使用 OutprocLoader 对象,该对象实现了 IEngineLoader 接口。若将其用于特定账户,可能需要相应权限才能以这些账户运行 OutprocLoader。
// 为每个线程创建单独的 OutprocLoader 对象,并加载一个 Engine 实例
IEngineLoader engineLoader = new FREngine.OutprocLoader();
IEngine engine = engineLoader.InitializeEngine( customerProjectId, LicensePath, LicensePassword, "", "", false );
// 我们已在单独的进程中获取到 Engine
try {
...
} finally {
engineLoader.ExplicitlyUnload(); // 不再需要时,可以将其卸载
engineLoader = null;
GC.Collect();
GC.WaitForPendingFinalizers();
}
此外,您还可以使用 IHostProcessControl 接口来管理主机进程的优先级,并控制其是否仍在运行。
- 可以使用 DCOM Config 实用程序设置账户权限 (可在命令行中键入 DCOMCNFG,或依次选择“控制面板”>“管理工具”>“组件服务”) 。在控制台树中,找到“组件服务”>“计算机”>“我的电脑”>“DCOM Config”文件夹,右键单击 ABBYY FineReader Engine 12.5 Loader (Local Server),然后单击“Properties”。此时会打开一个对话框。单击“Security”选项卡。在“Launch Permissions”下,单击“Customize”,然后单击“Edit”,以指定哪些账户可以启动该应用程序。
请注意,在 64 位操作系统上,已注册的 DCOM 应用程序可在 32 位 MMC 控制台中使用,可通过以下命令行运行该控制台:
- 要在最终用户的计算机上安装应用程序时注册 FREngine.dll,请使用 regsvr32 工具。如果您使用的是 64 位操作系统,默认会运行 64 位版本的 regsvr32。请使用以下命令行:
regsvr32 /s /n /i:"<path to the Inc folder>" "<path to FREngine.dll>"
- 将 Engine 实现为进程外服务器时,可通过将 MultiProcessingParams 对象的 MultiProcessingMode 属性设置为 MPM_Sequential,来指定文档处理的顺序模式。
ABBYY FineReader Engine 发行包包含 EnginesPool 示例,该示例展示了使用Engine 池带来的速度提升,并提供了一个可直接使用的实现,可作为您自行开发应用程序的起点。有关如何实现自定义图像源、处理异常以及控制 CPU 核心使用的详细信息,请参阅此示例的源代码。
FRDocument
BatchProcessor
MultiProcessingParams
迭代文档页面
加载 Engine 对象的不同方式
在多线程服务器应用程序中使用 ABBYY FineReader Engine