HALCON 通过线程安全和可重入特性支持并行编程,即不同线程可以同时调用 HALCON 算子,而无需等待。不过,并非所有算子都是完全可重入的。本节将对 HALCON 的重入性进行更深入的探讨。此外,它还指出了在编写使用 HALCON 的并行程序时应注意的问题。
example\c 目录中的示例程序 example_multithreaded1.c 演示了如何使用 HALCON/C 并行提取电路板上不同类型的组件。
此外,HALCON 还提供了用于同步线程的特殊算子(参见 "多线程算子" 一节 )。
事实上,HALCON 算子的重入性有不同的 "级别":
- 重入
如果一个算子可以同时被多个线程调用,且与调用的数据无关,那么它就是完全重入的。
当多个线程使用相同的数据对象(如相同的图像变量)时要特别注意。在这种情况下,必须使用相应的并行编程机制(互斥、信号量)手动同步对该变量的访问。更好的办法是尽量避免这种情况,即使用局部变量。请注意,这不是 HALCON 的特殊问题,而是一般并行编程的问题。
- 本地
标记为本地的算子只能在实例化相应对象的线程中调用。
- 单次写入,多次读取
只有当不同的调用线程处理不同的数据时,才能同时调用某组算子。
由于一般不建议使用这种线程行为,因此 HALCON 不会主动阻止这种行为,从而节省了开销。这意味着,如果您(不小心)用相同的数据同时调用此类算子,虽然不会阻塞线程,但可能会产生不良后果。
- 互斥
某些算子不能被多个线程同时调用,但可以与其他 HALCON 算子并行执行。
- 独占
一组算子只能由 HALCON 执行,也就是说,在执行该算子时,所有其他线程都不能调用另一个 HALCON 算子。
- 独立
一组算子的执行独立于其他算子,甚至是排他性算子。
如前所述,参考手册中对 HALCON 算子的描述包含一个名为 "执行信息" 的条目,其中规定了算子在使用 HALCON 时的行为。如上所述,该条目指定了重入级别。
一般来说,多线程编程必须考虑以下问题:
- 线程数 ≤ 处理器或内核数
如果使用的线程数量超过了处理器或内核的数量,那么由于同步开销,您的应用程序实际上可能会比以前更慢。请注意,在计算线程数时,只有所谓的工作线程才是相关的,即持续运行/工作的线程。
- 局部变量
如果可能,请使用局部变量,即在使用变量的线程中实例化变量。如果多个线程使用同一个变量,则必须使用适当的并行编程结构(互斥、信号量;详情请参考编程语言的文档)同步它们对变量的访问。
使用 HALCON 时,请注意以下问题:
- 初始化
HALCON 在算子首次调用时进行隐式初始化。在初始化过程中,除其他外,将检查许可证、设置 HALCON 内存管理、启动用于内部算子并行化的线程池、初始化内部系统参数和同步对象。在多线程环境中,该初始化过程是线程安全的。
请注意,某些系统参数的默认值可以在初始化过程之前更改。请比较 include/HGlobal.h 文件和本文档中对相应参数的一些引用。如果使用,请确保在多线程环境中调用第一个算子之前设置了所有默认值。
- 输入/输出和可视化
请记住,创建或删除文件的算子只能专用,即其他线程必须等待。
程序员必须确保线程不会同时访问同一个文件(或句柄)!
有关不同操作系统上的可视化问题,参见 "图形的线程问题" 一节 。
- 多线程与自动并行化
如果要在多线程程序中明确平衡多个处理器或内核的负载,我们建议您要么关闭自动并行化机制以获得最佳性能,要么减少自动并行化机制使用的线程数,使线程总数不超过处理器或内核数。如何关闭自动并行化机制或减少内部线程数,参见 "自定义并行化机制" 一节 。
在算子部分 系统 → 多线程 一节中,HALCON 提供了用于创建和使用同步对象的算子,如互斥、事件、条件变量和屏障。
有了它们,你就能以一种与平台无关的方式同步线程。不过要注意的是,到目前为止还没有提供创建线程的算子。
HALCON 目前提供以下并行编程示例(路径相对于 %HALCONEXAMPLES%):
HALCON/C
- c\source\example_multithreaded1.c
两个线程并行提取电路板上的不同元素
HALCON/.NET
- c#\MultiThreading (C#)
用三个线程执行图像采集、处理和显示
- hdevengine\c#\MultiThreading (C#)
通过两个线程并行执行同一个 HDevelop 程序,使用 HDevEngine
- hdevengine\c#\MultiThreadingTwoWindows (C#)
使用 HDevEngine 通过两个线程并行执行不同的 HDevelop 程序
HALCON/C++
- mfc\FGMultiThreading (using MFC)
在两个线程中执行图像采集、显示和处理
- hdevengine\mfc\source\exec_programs_mt_mfc.cpp
使用 HDevEngine 和 MFC 并行执行用于图像采集、数据码读取和可视化的 HDevelop 程序
- hdevengine\cpp\source\exec_procedures_mt.cpp
使用 HDevEngine 并行执行 HDevelop 程序