关于Python multiprocessing.Array创建的共享内存无法删除的问题

        由于GIL(global interpretor lock)机制,Python多线程(multi-thread)操作,不是真正意义上的并行多线程(具体请看这)。因此,Python的并行工作一般采用多进程的方式进行(Multi-process)。多进程相对于多线程最大的问题的数据通信问题,特别是大数组的交换会很慢。

        最近项目组在实现Python多线程计算时,采用了pprocess库进行算法的并行。数据交换采用multiprocessing.Array创建数组,传给各个线程用于数据的交换。然而,计算过程中间出现了内存泄漏问题,导致最后内存不够。最后发现是,multiprocessing.Array创建的共享内存无法删除导致。

         先上简单测试代码:

import numpy as np
import multiprocessing as mp
import ctypes
import os
import time
import mmap

def parallel_doSomeWork(train_data):

    train_data[0, 0 ,0] = 1.0

def experiment(n):

    # creating shared varibale train_data, that can be accessed by multiprocessors
    train_data_s = mp.Array(ctypes.c_float, 100*n * 64 * 64)
    train_data = np.frombuffer(train_data_s.get_obj(), dtype=np.float32).reshape(100*n, 64, 64, 1)

    parallel_doSomeWork(train_data)
    train_data = 0
    train_data_s = 0
  
def main():

    for n in range(1,300):
        print("loop %d:" % n)
        # print memory usage info
        val = os.system("free -m")
        print val

        experiment(n)

        # print memory usage info
        val = os.system("free -m")
        print val
        print()
        print()

if __name__ == '__main__':
    main()

        我们用mp.Array创建了一个共享内存,用于多进程数据的交换。(由于原因与多进程无关,此处简单化parallel_doSomeWork)使用完毕后,我们将它置为0,“删除”其内存。在一般变量上,这个方法是简单快速有效的。然而,由于mp.Array的特殊性,并没有真正删除,shared memory显示内存依然被占用。

        最终解决方法:

        将train_data_s=0这一句替换为:

    dataheap = train_data_s.get_obj()._wrapper._heap
    datastate = train_data_s.get_obj()._wrapper._state
    arenaobj = datastate[0][0]
    arenaobj.buffer.close()
    heap.BufferWrapper._heap = heap.Heap()
         长话短说,原因一定是共享内存采用new的方式,在堆区新建了内存,而没有delete。想必multiprocessing一定有其原因。不过既然它本身不主动删,我们又需要删除,那我们就只好自己动手了。亲测300个循环下来并没有什么问题,方法应该是有效的。

         如果有大牛知道更好的解决方案,也请不吝指教。

你可能感兴趣的:(ubuntu,python)