葛 亮,蒋 炎,张 禾,邓 勇,肖小汀,薛志波,张嘉伟
(1.西南石油大学机电工程学院,四川成都 610500;2.西南石油大学电气信息学院,四川成都 610500;3.中海油田服务股份有限公司油田技术研究院,河北三河 065200)
传统的上位机测试系统或应用多采用串行模式,使整个测试系统或者应用在使用当中只能执行当前正在执行的操作,而无法同时响应用户的其他操作。当执行周期过长时,应用程序相当于被挂起,在用户看来应用程序好像出现卡顿或死机现象,只有当整个应用程序内的所有事件、所有子程序完全被执行完后,应用程序的线程才能空闲下来,用户才能对该应用执行其他操作。但是,这对调度任务特别复杂或者测试周期长的应用程序来说是无法接受的。因此,优化测试模式、提高测试效率是十分必要的。
针对串行模式周期时延和调度问题,2012年,吴忠锴、梁志剑、马铁华等学者在研究“力学实验数据采集系统软件”时采用生产者/消费者模式[1-3]来避免数据采集周期与数据处理周期不一致造成的数据丢失或数据重复利用的问题[4]。2020年,为了满足汽车稳定控制系统(ESC)电子控制单元多个产品同步执行测试的需要,刘规划对多线程以及并行测试技术进行了研究,开发了基于LabVIEW和TestStand的汽车ESC产品并行测试系统,解决了多线程软件编程中遇到的竞争、资源冲突、死锁等问题[5]。2001年,文献[6]在传统的测试结构的基础上对并行架构和网络技术做出详细的理论研究,尤其是其中的分布式系统概念、远程测量、共享数据等并行技术和多线程技术方面。2017年,文献[7]利用LabWindows/CVI研究了“一种通过USB线连接PC机的液晶眼睛控制器”,该控制器的软件部分采用多线程技术与仪器进行数据交互,使得在廉价而多功能的医疗仪器中实现高效的算法成为可能。
通过研究发现,多数学者在传统测试模式出现问题的基础上提出了许多研究思路,这加速了并行技术[8-14]、多线程技术[15-19]在工控测量行业中的发展。但这些研究在成型的测试框架和多线程优化模型上还存在不足,系统性不强。
本研究根据现代具有多核心和多线程微处理器的计算机技术体系,以核磁测井项目为例对多线程优化机理进行研究,建立核磁测井仪器的多线程优化模型,开发出高温多维核磁测井仪器软件(EMRT2.0),并与一维核磁测井仪器软件(EMRT1.0)进行对比试验测试。该多线程优化模型应用多线程技术和并行测试技术,将CPU资源利用到最佳。
LabVIEW是自动多线程的编程语言,如果VI的代码并行执行,LabVIEW就将它们分配在多个执行线程内同时运行。一般情况下,运行一个 VI,LabVIEW 至少会开辟2个线程:一个界面线程(UI Thread),用于处理界面刷新,用户对控件的操作等;一个执行线程,负责VI除界面操作之外的其他工作[20-21]。
在并行执行时,LabVIEW 会自动将测试任务安排在不同线程下同时运行,以提高程序的执行速度,节省程序的运行时间。今后多核计算机将成为主流配置,多线程的优势会更为明显。
从内部来看,在LabVIEW的编程环境中,常用的优化机制有局部变量、全局变量、节点、引用及队列等。这几类优化机制对计算机硬件资源配置的要求和消耗各不相同,为了更好地实现多线程优化模型的优化和对CPU资源的利用达到最优,需要合理使用这些常用优化机制。
(1)局部变量。局部变量的使用范围被限制在一定区域,其定义和使用效果与C语言相同。局部变量必须有与之对应的控件,一个控件可以有一个或多个局部变量。局部变量的作用是在局部区域内传值,可以作为输入也可以作为输出。每个局部变量都需要复制控件内的数据,进而导致消耗更多的内存。
(2)全局变量。全局变量的功能与局部变量类似,不同在于全局变量的作用范围更广,可以做到跨线程和跨VI。同样,局部变量潜藏的问题,全局变量也具备。
(3)节点。节点在LabVIEW中使用非常普遍。节点用于访问控件的属性和方法。但节点的执行效率较低,甚至低于全局变量。
(4)引用。引用通常与节点配合使用,将控件的属性和方法绑定在类中。引用使程序得到简化并减少节点和局部变量的使用。
(5)队列。队列状态机把将要执行的状态编排入队,队列中的状态名与状态机的各状态一一对应,用来控制状态的转换顺序。执行过的状态,其状态名将从队列中删除,同时根据运行状态和触发事件,新的状态名将会被添加到队列中。在数据传递过程中,队列是LabVIEW处理线程间数据传递的主要方法,它需要严格设置队列名称和队列数据传递类型。
从计算机的角度来讲,可以将多线程技术理解成CPU在时间轴上做了一个时间分割,将时间分割成不同长度的时间片。每个线程被分配不同的时间片,而每个时间片又含有各自独立的堆栈和CPU寄存器状态,同时在每个时间片内又将执行相应的任务。当任务结束后,优先级次高的线程将被创建和执行。在某个时刻,CPU仅执行某一个时间片内的线程[22]。从处理速度上分析,CPU切割的时间片极其短暂,肉眼无法分辨,使得多个线程看起来是在同时运行[23]。
在实际应用中,由于硬件资源有限,单个硬件资源配合上位机测试系统使用不存在资源调度,而多个硬件资源或多个测试模式配合上位机测试系统使用存在资源调度。资源调度是在不冲突的情况下,有序地完成单个测试模式对硬件资源的启用和释放的过程。它分为2种。第一种,上位机测试系统通过调度多个硬件资源,使系统内每个硬件资源在某个时间片内得到运行。第二种,上位机测试系统针对单个硬件资源开发多个测试模式,每个测试模式在不同的时间节点去调用该硬件资源。
本研究的核磁测井仪器的多线程优化模型根据第二种方式提出。在综合常用优化机制的基础上,选择采用队列和引用的方式来构建多线程优化模型,对同一个核磁测井仪器做不同的功能测试。整个多线程优化模型由图1和图2组成,图2为图1中主线程和副线程的优化框架模型,主、副线程采用相同的优化框架模型。
图1 核磁测井仪器多线程资源调度模型图
图2 核磁测井仪器多线程优化框架模型图
如图1和图2所示,该多线程优化模型内部做出以下优化。
(1)线程划分。多线程优化模型内部被分解成主线程、副线程、队列线程。这3种线程再次细分成数据采集、数据传输、数据处理、数据显示、数据存储、数据回放等辅助线程。线程划分的方式使测试任务和资源调度更为便捷。
(2)模式调整。多线程优化模型将EMRT1.0的串行模式调整为并行模式,即EMRT2.0的主线程与副线程能够并行运行。并行测试方式使EMRT2.0能够解决EMRT1.0周期时延问题。
(3)数据处理方式改进。多线程优化模型将EMRT1.0调用MATLAB脚本的方式改进为调用MATLAB生成程序集的方式来实现孔隙度功能;这种方式解决了EMRT1.0调用脚本时依赖MATLAB开发平台的问题并增加程序的移植性。
(4)类封装传值。多线程优化模型对控件进行类封装,即控件的属性和方法通过类封装后进行传递。类封装方式优化了整个控制台的代码,避免当EMRT2.0随着功能复杂化后需要增加CPU的负荷来保存程序代码而耗费大量时间的问题,避免EMRT2.0频繁复制和刷新控件内的值。
(5)簇封装。多线程优化模型将EMRT2.0界面控件通过簇进行封装。簇封装方式为控制台和前端界面节省更多空白空间,便于维护和阅读。
如图1所示,上位机由主线程、队列线程、副线程构成。这3个线程内部由相应的辅助线程组成,辅助线程在上述3个线程被创建后由软件开发平台内部自行创建。主线程和副线程都设置有固定时间去轮询来自队列线程的消息,即线程内部每间隔固定的时间将会去执行如图2所示的IDLE部分。IDLE部分是主、副线程较为重要的设置部分,它在超时的情况下将线程消息或Debug内的消息送入队列。经过试验验证,主、副线程的超时设置必须大于0,否则随着EMRT2.0启动,计算机的CPU占用率会飙升至90%以上而正常情况下仅为1%。下位机由核磁测井仪器构成。
2.3.1 事件触发线程
(1)用户事件触发线程。用户事件是由用户通过点击前端界面控件从而产生一系列的响应事件,该线程的启用和销毁具有随机性。
(2)数据事件触发线程。数据事件触发线程的启用由以下过程完成触发。当副线程完成一周期的数据采集后,队列线程将数据传送至图2中主线程的线程消息部分,然后由进入IDLE部分的新增消息去启用数据处理线程和数据显示线程。从线程耗时角度分析,数据采集线程与数据处理线程在整个测试周期内耗时最长。
如图3所示,若采用串行模式,当前周期需要等待数据处理完成后才能进行下周期的数据采集。当数据处理耗时过长时,串行模式会影响到下周期的数据采集,这相当于整个周期被强制延长。
图3 数据采集与处理关系图
如果采用并行模式,副线程负责数据采集,主线程负责数据处理。由于2个线程的相关性较低,即使数据处理耗损时间稍长也并不阻碍副线程的数据采集。这表明前一次的数据处理和后一次的数据采集是否同时进行取决于前一次数据处理的复杂程度。
2.3.2 数据分析处理线程
2.3.2.1 数据处理线程
数据处理线程的启用是由图2中主线程的“线程消息”入列后再触发。队列中的数据属于原始数据。原始数据包含队列名、队列命令、采集数据、选择枚举以及计数器,其中计数器仅存在于主线程,副线程不含计数器。另外,在整个采集过程中,EMRT2.0需要将数据移位缓冲在临时缓冲区域内,而且几乎所有采集的数据都需要临时缓存。因此,为了优化EMRT2.0的数据处理部分,在数据处理线程中做出以下优化。
第一,为了减少LabVIEW在VI运行状态下对内存资源的消耗,EMRT2.0的前面板摒弃使用较大的数组和层次化数据结构。因为LabVIEW对这类数据需要建立较大的缓冲区,这导致LabVIEW无法快速处理此类结构,占用更多内存。
第二,由于LabVIEW开发平台自身不能进行缩放,进而导致程序布局随着功能复杂后变得冗杂,无论是代码维护还是项目对接都将变成棘手的问题。EMRT2.0采用子VI的方式来避免这类问题。
第三,利用第三方软件对复杂算法进行封装。例如,在数据处理线程中会加载经过Visual C++编译的T2反演库和MATLAB编译的.Net程序集。从软件的侧重点上来讲,这符合多线程优化模型的优化思想,开发平台选择开发周期短的LabVIEW,重量级算法选择MATLAB和Visual C++,从而提高EMRT2.0的可移植度。
2.3.2.2 数据显示线程
数据显示线程的启用由以下过程触发。当图1中的原始数据完成数据处理后,由图2中的“下一条入列消息”将经过数据处理后存入临时缓冲区内的采集数据送至数据显示线程进行显示和刷新。为了优化数据显示线程,根据多线程优化模型的优化思想。控制台和前端界面的控件采用簇的方式进行捆绑,控制台中的控件尽可能直接与子VI相连接。捆绑方式减少代码的过度暴露,增大面板预留空间,增强代码可读性。
2.3.2.3 数据存储线程
数据存储线程的启用是在图1中由用户触发界面控件后产生。本研究提到的数据存储线程不仅用于储存测试数据,该线程还用于读取配置数据。
一方面,随着功能复杂化后,每个测试模式都需要单独创建配置表信息。从EMRT2.0的测试逻辑来看,一次完整且连续的数据采集需要对核磁测井仪器做出准确的配置。因此,主线程中的数据存储线程需要将用户操作的最新界面配置表信息存入ACCESS数据库,而副线程的数据存储线程需要从ACCESS数据库读取最新的配置表信息来配合副线程中的数据采集线程使用。为了优化配置信息,根据多线程优化模型的优化思想,将配置信息写入ACCESS数据库和从ACCESS数据库读取配置信息都被封装成子VI并留有枚举选择框,其中枚举选择框对应所有测试模式的配置信息表。此外,对于ACCESS数据库,该数据库属于轻量级数据库,功能强大且移植性强,用户可以不依赖服务器就能访问数据库。重要的是,ACCESS数据库能够脱离OFFICE环境,适合移植。
另一方面,由于测试模式的原始数据长度范围在500字节~70 000万字节之间,因此测试数据选择含有逗号分隔符的CSV文件进行存储。该格式文件有2个优点:第一,利用LabVIEW自带的含有格式限制的读取函数,可以一次快速读取到程序中;第二,CSV文件属于文本文件,对存储没有行限制,相较于其他EXECL格式文件具有更小的体积,有利于测试数据进行存储操作。
2.3.2.4 数据回放线程
数据回放线程的启用是在图1中由用户触发界面控件后产生。该线程便于用户查询过去的测试信息和错误日志,有利于检查核磁测井仪器出现的各种问题。从EMRT2.0测试逻辑的角度进行分析,数据回放操作只在主线程进行,该线程将过去存入数据库和CSV文件中的历史数据提取到主线程,并由主线程开启数据处理和数据显示线程来完成数据回放操作。
2.3.3 队列线程
队列线程的本质是队列技术[24]。队列线程在EMRT2.0中负责跨线程和跨VI传输命令和数据,起到中间桥梁的作用。如图1和图2所示,主线程和副线程通过队列衔接。主线程负责发送采集命令和送数命令给副线程,而副线程负责发送原始数据和少量资源调度命令给主线程。可以看出,在队列的衔接下,主、副线程采用并行测试技术和多线程技术独立运行在相应的线程,互不干扰,极大提高了测试效率。
2.3.4 副线程
如图1和图2所示,EMRT2.0将所有的测试模式单独划分成副线程,副线程主要负责数据采集任务。在循环周期内,主线程负责通过队列线程将命令送至副线程,副线程负责与核磁测井仪器通过USB协议进行数据交互,原始数据通过队列线程传送到主线程。
前文详细介绍了多线程优化模型的模型构建和模型分析部分,对EMRT2.0的实现奠定理论基础。本节基于多线程优化模型设计的EMRT2.0项目模型如图4所示,EMRT2.0项目实物如图5所示,EMRT2.0界面实物如图6所示,EMRT2.0框架实物如图7所示。
图4 EMRT2.0项目模型图
图5 EMRT2.0项目实物图
图6 EMRT2.0界面实物图
如图4和图5所示,整个模型实例分为01_Main、02_IC、03_CPGM、04_DECPGM四大板块。项目模型和实物完全吻合,4个仪器标定模式和18个测井模式,共22个测试模式。所有的测试模式被划分为副线程,负责数据采集任务,可以看出,副线程与主线程采用相同的框架,都包含有00_Class、01_Frame、02_SubVI、03_Queue、04_State、05_ErrorState、06_Debug、07_Configure、08_File 8部分。00_Class将测试模式和框架本身含有的参数封装在类中,负责绑定方法和属性;01_Frame包含如图7所示的5个线程框架VI,从左到右分别为Create、Update、Idle、Retrieve、Delete,负责04_State中各种线程消息的循环;在主线程中,02_SubVI包含大量的数据处理VI和配置VI,负责数据处理和初始化;03_Queue包含队列VI,负责承载队列消息;05_ErrorState负责记录测试的错误日志和执行错误处理;06_Dubug负责手动调试线程;07_Confiure负责保存大量配置文件和测试数据,如LabVIEW调用ftd2xx.dll[25-26]动态库去执行USB通讯的各种子VI、T2反演动态链接库以及孔隙度算法库等;08_File为预留线程文件空间。
图7 EMRT2.0框架实物图
核磁测井仪器测井模式图如图8所示,图中有4个仪器标定模式和18个测井模式,EMRT1.0包含4个仪器标定模式和前8个CPMG测井模式,EMRT2.0包含全部测试模式。从实验结果的角度出发,EMRT2.0在EMRT1.0的基础上增加了测井模式和更改了命令参数,且本研究只需验证多线程优化模型。因此,前面所述的问题并不影响实验效果,两个版本的测试软件只需保证对比的测试模式相同即可。
图8 核磁测井仪器测井模式图
为了让实验更具有对比性,表1的计算机硬件配置属性严格低于表2。
表1 实验条件1
表2 实验条件2
表3和表4分别为实验条件1和2的测试结果。
表3和表4中所涉及的“×”表示不存在或无严格设定标准,例如表3中版本1.0的扫频模式对应的调度模式表示EMRT1.0为串行模式,没有进行严格的线程划分,故不存在调度时间。表3和表4中所测试的调度时间、采集时间、传输时间、处理时间、CPU占用率以及内存占用均是平均值。通过上述两表所测试的优化指标数据,可以得到以下信息:
(1)整体对比表3和表4,当硬件资源的配置属性得到提升后,EMRT1.0与EMRT2.0的各项指标得到大幅度提高。
(2)对比表3和表4的测试数据,1.0版本下FBW2F模式的设定周期为3 s,实际周期为4~6 s,而2.0版本FBW2F模式的设定周期为3 s,实际周期为2~3 s。因此,可以看出EMTR2.0的实际周期低于设定周期并在EMRT1.0的基础上将测试周期缩短为原来的1/2。
(3)对比表3和表4中1.0版本的测试数据,MATLAB的CPU占用高达85%(表3)、60%(表4)以上。
(4)对比表3和表4中1.0版本和2.0版本的测试数据,EMRT2.0在EMRT1.0的基础上脱离了MATLAB开发平台,不再占用计算机的CPU资源和消耗计算机的物理内存;此外,EMRT2.0的仪器标定模式和测井模式的物理内存与CPU分别达到406.9~585.2 MB(表3)、372.4~537.0 MB(表4)和4.0%~62.0%(表3)、1.4%~6.2%(表4),而EMRT1.0与之对应的仅为155.4~177.3 MB(表3)、144.5~145.3 MB(表4)和3.0%~12.0%(表3)、0.4%~1.5%(表4),这是由于EMRT2.0在原有模式上增加了10个测井模式和孔隙度算法功能。不难发现,EMRT2.0增加功能的同时,充分利用了计算机的资源,这说明EMRT2.0整体提升了测试性能并优化了资源调度。
表3 实验条件1测试结果
表4 实验条件2测试结果
本研究对核磁测井仪器的多线程优化模型进行研究,并通过模型构建、模型分析、模型实现以及对比试验测试验证了多线程优化模型的可行性与有效性。本研究的主要内容如下:
(1)基于LabVIEW编程环境与优化机理,结合多线程技术和并行测试技术,建立核磁测井仪器的多线程优化模型。
(2)基于多线程优化模型对核磁测井仪器的资源调度和多线程功能与关系进行分析,能够满足多任务调度测试和并行技术需要。
(3)基于多线程优化模型开发出EMRT2.0并选用测试周期、CPU、物理内存作为评价指标。通过表4中EMRT2.0与EMRT1.0的部分模式对比试验可知,EMRT2.0的实际测试周期缩短为EMRT1.0的实际测试周期的1/2,CPU的利用率从0.4%~1.5%提升至1.4%~6.2%,MATLAB的CPU利用率和物理内存占用降至0。
本研究验证了核磁测井仪器多线程优化模型的正确性,对资源调度、串行模式的周期试验、线程间大数据传输、资源冲突、程序移植等方面具有指导意义。