Python双线程使用

来源:互联网 发布:亚思捷软件 编辑:程序博客网 时间:2024/05/20 18:16

最近研究人脸匹配,在人脸匹配过程中,由于摄像头输入的人脸要与数据库中的人脸比较,但由于数据库中的人过多,逐一匹配速度可能会降低,故选用双线程实现匹配加速,本文主要就python如何使用双线程进行记录。 由于Python的解释器CPython的原因,Python并不能使用双线程。因为CPython存在GIL锁,具体原因:

因为Python的线程虽然是真正的线程,但解释器执行代码时,有一个GIL锁:Global Interpreter Lock,任何Python线程执行前,必须先获得GIL锁,然后,每执行100条字节码,解释器就自动释放GIL锁,让别的线程有机会执行。这个GIL全局锁实际上把所有线程的执行代码都给上了锁,所以,多线程在Python中只能交替执行,即使100个线程跑在100核CPU上,也只能用到1个核。 摘自http://www.liaoxuefeng.com/wiki/001374738125095c955c1e6d8bb493182103fac9270762a000/001386832360548a6491f20c62d427287739fcfa5d5be1f000(侵权删)

故只能使用单核运行,而我的机器是单核双线程。故使用单核上的两个线程去完成任务。 至于为何能使用单核双线程,也在摸索中。 虽然GIL会让机器只能使用单核,但是针对IO口操作,仍可以实现单核多线程。 因此,受到上面的启发,而最近做人脸匹配,人脸库的比较过于耗时,故采用双线程,分两个路。具体流程图如下:


使用双线程,每个线程处理一半的人脸库,若有一个线程判断符合小于阈值θ,则直接判定是同一个人。另一个线程也直接结束。若两个线程都不小于阈值θ,则判定不是同一个人。

由于python只能用两个线程,故使用主线程以及线程1

具体的程序如下:

for Num in range(Boxnum):        #t3=time.time()       # Calculate_Distance_1(Feature, feature2[Num], metric, min_predicts, Lists_Num)       # Calculate_Distance_2(Feature, feature2[Num], metric, min_predicts, Lists_Num)        Thread1=threading.Thread(target=Calculate_Distance_1,args=(Feature, feature2[Num], metric, min_predicts, len(Lists)))        Thread1.start()        #主线程运行,加上上面的线程,共2线程        global ThreadingState1        global ThreadingState2        ThreadingState1 = 0        ThreadingState2 = 0        i = 1        if len(Lists) / 2 is not (len(Lists) + 1) / 2:  # 奇数            for sublist in range((len(Lists) - 1) / 2):                predicts2 = pw.pairwise_distances(Feature[i], feature2[Num], metric=metric)                i = i + 2                if predicts2[0][0] > 0.12:                    if ThreadingState1 is 1:                        break                    if predicts2[0][0] < min_predicts:                        min_predicts = predicts2[0][0]                else:                    min_predicts = predicts2[0][0]                    ThreadingState2 = 1                    break        else:            for i in range(len(Lists) / 2):  # 偶数                predicts2 = pw.pairwise_distances(Feature[i], feature2[Num], metric=metric)                i = i + 2                if predicts2[0][0] > 0.12:                    if ThreadingState1 is 1:                        break                    if predicts2[0][0] < min_predicts:                        min_predicts = predicts2[0][0]                else:                    min_predicts = predicts2[0][0]                    ThreadingState2 = 1                    break        #Thread2=threading.Thread(target=Calculate_Distance_2,args=(Feature, feature2[Num], metric, min_predicts, len(Lists)))        #Thread2.start()        Thread1.join()
因为最多单核双线程,故仅开一个线程即可。

python中使用多线程需要使用import threading。为了让两个线程之间互相通信,使用全局变量

ThreadingState1
ThreadingState2
并在函数开始部分声明global XXX

最终实现了双线程通信。

但是存在一些问题,并没有提升速度,反倒变慢了

线程数

检测到

检测不是我

单线程

0.071s

0.083s

双线程

0.077s

0.082~0.084s

可以看出,并没显著提升速度,反而有点下降。原因可能是:

线程的开启、结束等原因会浪费时间,而人脸库的匹配并不是非常耗时的行为,因此节省的时间很有限,故并无明显提升。

之前以为的人脸匹配导致人脸速度过慢,实际上是错误的,是由于报警模块耗时严重拉低了整个系统的速度。

由于非配合时人脸识别门禁系统还处于研究状态,仍然存在人脸特征提取不良好的情况,例如眼镜对人脸影响较大,故在一个月内,继续研究问题,并将改进识别,到时,会再开一篇人脸识别系列博客专门讲述人脸识别所做的项目,以及非配合式的人脸解决方案。届时会在github放出代码。


原创粉丝点击