Python多线程调用C无法绕过全局解释器锁(GIL)

时间:2017-04-26 17:11:04

标签: python multithreading ctypes gil

我试图编写一个覆盆子pi 3相机(" picamera")来改善其采集特性。 picamera非常精确地获取高达90Hz的帧(GPU具有独立时钟),但是树莓派和Linux操作系统(jessy) - 在保存到磁盘时会定期挂起或冻结。当pi冻结时,来自相机的帧会丢失到以太网中。我不知道为什么pi会冻结,但我认为带宽或线程任务在某处都是瓶颈。

所以我认为编写python代码将帧保存到内存中 - 然后将内存指针传递给C代码,这些代码将独立(并且在其自己的时间)将数据保存到磁盘 - 将克服了冰冻问题。我使用基于ctypes的python调用将python数组的内存指针发送到C.

这是粗略的布局:

picamera (python) -------------- ongoing picamera processing...
                 \
                  -> python thread -> call C-based saving (dll/ctypes)

这里有一些snipets代码(picamera有几千行代码):

#Main python code to initialize thread call to python function:
...    
self.image_stack_0=((ct.c_char*int(self.n_pixels)**2*3))) #init memory buffer
t = threading.Thread(target=self.c_saving)  #call python routine on 2nd thread
...

#3-line python routine being called above
def c_saving(self):
   ''' Code to save data to disk using C while ongoing acquisition '''
    _sum = ct.CDLL('/home/pi/murphylab_picam/save_c.so')
    _sum.save_c.argtype = (ct.POINTER(ct.c_int32), ct.POINTER(ct.c_int32), ct.POINTER(ct.c_char), ct.POINTER(ct.c_char))
    _sum.save_c(self.save_block, self.frame_ctr, self.image_stack_0, self.image_stack_1)

因此代码运行良好,但写入磁盘继续导致定期(虽然不太严重)挂起/冻结到python帧采集。

我对全局解释器锁(GIL)的理解很少,但似乎只是调用一个python线程 - 然后调用C代码 - 不会导致C代码独立地运行第二核心(树莓派3有4个核心)。

有没有办法确保被调用的C模块(它只是跟踪帧缓冲区数组并定期写入)将在第二个核心上运行?多处理可能是一种解决方案,但代码已经很复杂,而且我不确定如何跨核心共享内存地址。

感谢您的阅读。

编辑:感谢您的评论。我通常在我的工作站上使用多处理,但问题是我需要在初始化和运行python代码后生成并行进程。据我所知,多处理调用在运行相应的函数时锁定python代码(尽管在不同的内核上)。

但是是一个线程调用后跟多处理调用,然后调用C代码可能吗?像这样:

picamera (python) -------------- ongoing picamera processing...
                     \
                      -> py thread -> py multiprocessing call ->  C-code (dll/ctypes)

它看起来像一个蜘蛛网,并没有认为它会起作用,但也许它确实如此。有什么意见吗?

0 个答案:

没有答案
相关问题