多线程技术在移动设备增强现实 应用中的性能优化研究
2018-11-19龙云跃
张 生,龙云跃
(上海理工大学 光电信息与计算机学院,上海 200093)
0 引言
近年来,随着计算机硬件技术的不断发展,增强现实、虚拟现实技术开始从理论变为现实,出现了越来越多的增强现实应用及设备。相关产品主要分为两类:一类是增强现实头盔,比较具有代表性的是微软的Hololens增强现实头盔、谷歌的Google glasses,这两种属于独立增强现实设备,因为其具有自己的处理芯片,可以脱离计算机独立工作;另一类是智能手机,美国苹果公司与谷歌公司分别研发了自己的技术ARkit和ARcore,利用智能手机摄像头,使增强现实应用可以运行在手机上。由于智能手机的广泛普及,手机增强现实应用具有更好的发展前景与商业应用价值。
一般的智能手机由于其硬件的性能局限性(CPU频率低,内存小, GPU性能低),导致很多开发完成的AR应用虽然在台式计算机中可以流畅运行,且帧数稳定、图像质量较好,但当移植到手机上,则会出现明显的帧数降低、画面卡顿等情况,大大降低了使用体验。传统解决方案主要有:①使用对性能要求较低的3D模型;②降低画面质量参数(光照、帧数、色彩、分辨率等)。但上述方案都以降低画面质量为代价,所以在某些场景下并不是最佳解决方案。
1 增强现实性能优化研究现状
1.1 传统图像类应用性能优化研究
随着移动设备的普及以及移动应用的大量增加,特别是游戏、图像分析类软件的快速发展,使渲染性能优化成为移动图形类应用研发的一个核心问题。根据应用场景不同有各种不同优化方案,一类方案为优化渲染算法类,如张骥先 、罗蕾 、姜帆[1]提出的富媒体场景渲染优化策略,该优化策略从局部渲染与多边形填充两方面进行,通过跟踪场景变化的失效区域体现局部渲染;另一类则是对被渲染的场景与物体模型进行优化的方案,如江能兴、周淦淼[2]提出的基于3DMAX的三维模型优化策略,通过简化3D模型提高渲染性能。
1.2 增强现实应用性能优化研究
增强现实类软件与传统图形类软件的最大区别在于,其需要通过摄像头实时捕获真实世界的图像信息进行分析,并在真实世界基础上建立一个虚拟空间。所以对捕获到的图像进行分析与处理会造成很大开销,从而影响系统的整理渲染性能。
对于增强现实应用的优化,传统对被渲染的虚拟物体模型进行优化是一个可行方案,但是优化效果依赖于需要渲染的模型数量。如果应用本身需要渲染的虚拟物体数量不多,则该优化方案收益并不理想。目前学术界和产业界研究与使用最多的方案是对捕获到的图像进行处理,并建立虚拟空间的算法进行优化,如Arthur、 Guez、Joelle、Pineau[3]提出的多任务SLAM算法。
2 多线程技术在增强现实环境下的应用实验
一般增强现实应用的性能测试包括渲染性能与计算性能测试。计算性能测试与常规软件性能测试基本一致,采用一定约束,在其它条件不变的情况下,通过改变单一参数,比较软件运行时的内存开销、CPU占用及运算时间等[4]。渲染性能测试,主要关注的性能指标为屏幕分辨率、渲染帧数及渲染帧数稳定性。本文主要实验流程为在一个已搭建好的AR软件环境中,在其它参数及条件一致的情况下,通过将运算进行多线程分离,比较使用多线程与不使用多线程情况下的渲染性能,得出实验结果。
2.1 实验原理分析
采用多线程即应用程序可在同一时间里使用芯片的不同部分。虽然单线程芯片每秒能够处理成千上万条指令,但在任一时刻只能够对一条指令进行操作,而多线程技术可以使芯片同时进行多线程处理,由此芯片性能得到提升[5]。本文使用多线程方式,将增强现实应用中的屏幕渲染功能与图像分析功能分开为两个线程,屏幕渲染功能设置为主线程,图像分析功能设置为子线程,两个线程异步工作。主线程不必等待子线程,当子线程完成图像分析后,发送信号给主线程,从而使屏幕渲染功能可以保持流畅执行,提升画面渲染性能。
2.2 实验流程
2.2.1 单线程环境搭建
本文实验环境使用美国苹果公司ARkit搭建的一个智能手机增强现实应用,测试平台为Unity3D引擎。该应用的主要功能为通过摄像头捕捉图像数据进行图像识别,当识别到特定模式图像后,展示相关分析数据,主要工作流程如图1所示。只要软件处于开启状态,则必须进行屏幕渲染,在该流程下,每一个渲染帧中,都要等待图像识别到发送信号后,才可继续执行下一帧渲染,两个功能之间是同步关系。
图1 软件工作流程
其中,Update方法用于更新屏幕内容,运行在每一个渲染帧,每一次执行都需要等待图像识别功能的结束,根据patternFound信号量的真假情况,才能进行下一步操作。单线程环境执行流程核心代码如下:
...
//模式识别函数
PatternDetector patternDetector;
//需要匹配的模式
Pattern pattern
void Start()
{
pattern = new Pattern();
patternDetector = new PatternDetector();
//生成模式
patternDetector.buildPatternFromImage();
}
//Update方法会在屏幕刷新的每一帧执行
void Update()
{
//执行图像模式识别
patternDetector.detectPattern();
if(patternDetector.patternFound == true)
{
nextStep();
}
else
{
//do nothing
}
}//update
2.2.2 多线程技术引入
考虑到保持图像模式识别处理与屏幕渲染的同步会严重影响系统性能,将图像识别处理功能分离到子线程中进行,而屏幕渲染功能依旧为主线程。此时的软件工作流程如图3所示。屏幕渲染功能运行在主线程,图像识别处理功能运行在子线程。因为线程分离,主线程运行不依赖于子线程的运行。当图像识别处理功能未完成时,主线程会一直执行屏幕渲染功能;当子线程中图像识别完成时,发送一个完成信号给主线程,此时主线程再执行下一步操作,子线程任务完成并被挂起。
图2 多线程引入后的工作流程
其中, Update方法用于更新屏幕内容,运行在每一个渲染帧,主线程执行屏幕渲染工作,子线程detectThread进行图像模式识别及处理工作。每一帧中,主线程都会对isComplete信号量进行校验,如果为假,则继续执行下一帧的屏幕渲染工作;如果为真,则开始执行触发相应功能。子线程完成图像模式识别后,将信号量isComplete设置为真,通知主线程,然后将isThreadRuning信号量设置为假,挂起子线程。在该流程下,屏幕渲染与图像处理处于异步执行关系中。加入多线程之后的执行流程核心代码如下:
...
//定义一个子线程,用来执行图像识别处理功能
Theard detectTheard;
//模式识别函数
PatternDetector patternDetector;
//需要匹配的模式
Pattern pattern;
//isComplete用于标识是否完成了识别
private boolean isComplete;
//isTheardRunning用来控制子线程开关
boolean isTheardRunning;
//Start函数用于初始化
void Start()
{
//子线程初始化
detectTheard =new Theard(detectPattern);
pattern =new Pattern();
patternDetector =new PatternDetector();
//生成模式
patternDetector.buildPatternFromImage();
}
// update函数会在屏幕刷新的每一帧执行
void Update()
{
//执行屏幕渲染
if(isComplete == true;)
{
nextStep();
}
}//update
...
//detectPattern在detectTheard线程中执行
void detectPattern()
{
if(isTheardRunning)
{
patternDetector.detectPattern();
if(patternDetector.patternFound == true)
{
isComplete =true;
isTheardRunning =false;
}
else
isComplete =false;
}
};
2.3 实验结果分析
2.3.1 渲染性能对比算法
本文主要考虑的渲染性能参数有:f为每一秒屏幕的刷新帧数;Ct为主线程当前占用CPU进行计算的时间绝对值,单位为s;Rt为GPU渲染线程花费时间,单位为s。对上述3个参数分别赋予不同权重参数P1、P2、P3,权重参数可根据对不同性能关注度的具体情况而定,在本文场景下,更加关注屏幕帧数,具体如式(1)所示。
(p1=0.8,p2=0.1,p3=0.1)
(1)
2.3.2 实验数据分析
保持其它条件不变,仅通过对多线程的引入进行多次实验,结果如表1所示。从表中可以看出,在本文软件环境下,多线程的引入对CPU和GPU影响较小,但能较好地提升渲染帧数。
表1 实验数据
3 结语
从实验数据可以看出,在CPU、GPU相同的情况下,以及相同的环境参数下,使用多线程将增强现实应用中的屏幕渲染与图像识别处理进行线程分离,可以有效提升画面帧数,提升幅度为25%,但同时可能增加约5%的CPU开销,而GPU开销基本不变。因此,在CPU占用量较小的图像处理类增强现实应用中,引入多线程可以明显提升渲染性能。