python共享内存

共享内存(Shared Memory)是最简单的进程间通信方式,它允许多个进程访问相同的内存,一个进程改变其中的数据后,其他的进程都可以看到数据的变化。

共享内存是进程间最快速的通信方式:
`进程共享同一块内存空间。
`访问共享内存和访问私有内存一样快。
`不需要系统调用和内核入口。
`不造成不必要的内存复制。

内核不对共享内存的访问进行同步,因此程序员必须自己提供同步。

使用共享内存:
`某个进程分配内存段。
`使用这个内存段的进程要连接(attach)这个内存段。
`每个进程使用完共享内存段后,要分离(detach)这个内存段。
`在某个地方,必须有一个进程来销毁这个内存段。

Linux的内存模型:
`每个进程的虚拟内存被分为页(page)。
`每个进程维护自己的内存地址到虚拟内存页之间的映射。
`实际的数据存在于进程的内存地址上。
`尽管每个进程有自己的地址空间,多个进程的映射还是可以指向相同的页。

所有的共享内存段的大小,都是Linux内存页大小的整数倍。
Linux的页大小是4KB,不过程序员应该使用getpagesize函数来获得这个值。

分配:shmget
`第一个参数是一个整型的键,用于指定要创建的段。无关的进程可以通过指定同一个键来访问同一段共享内存。
`使用常量IPC_PRIVATE作为第一个参数,可以避免键的冲突。
`第二个参数是分配的段的大小(字节数)。实际分配的字节数会舍弃多余部分到页大小的整数倍。
`第三个参数是位标志,用来表示创建的选项。
``IPC_CREATE:表明要创建新的共享内存空间。
``IPC_EXCL:总是和上一个标志一起使用。如果指定键的共享内存段已经存在,这个标志会导致调用失败;如果没有指定这个标志,调用会返回已经占用这个键的共享内存段。
``模式标志:9个bit的标志,和系统的文件权限使用相同的标志,不过执行标志无效。这些标志定义在<sys/stat.h>中。
`返回值是新创建的或者取得的内存段的标志符(SHMID)。

连接:shmat
`第一个参数是由shmget得到的标志符(SHMID)。
`第二个参数是指向你想要映射到的本进程的地址空间的指针。如果指定NULL,Linux负责选择一个可用的地址。

===================================================

python的共享内存

python的multiprocessing模块提供两种共享内存,sharedctypes与Manager,
Manager效率较低,但支持远程共享内存。
sharedctypes效率较高,快Manager两个数量级,在多进程访问时与普通内存访问相当
结果比较如下:
test array
elapsed 0:00:00.119707
test dict
elapsed 0:00:00.152856
test shared manager list
elapsed 0:00:37.87666
test sharedctypes list in main process
elapsed 0:00:00.154170
test sharedctypes list in subprocess
elapsed 0:00:00.303328
elapsed 0:00:00.327261
elapsed 0:00:00.349312
elapsed 0:00:00.318946
elapsed 0:00:00.364301
elapsed 0:00:00.370176
elapsed 0:00:00.343588
elapsed 0:00:00.348737
代码如下:


import array
from datetime import datetime, timedelta

size = 1000000
def tranverse(a):
    t = datetime.now()
    for i in range(size):
        a[i]
    print 'elapsed %s'% (datetime.now()- t)

a = array.array('i', [i for i in range(size)])
print 'test array'
tranverse(a)


a = {}
for i in range(size):
    a[i] = i
print 'test dict'
tranverse(a)


from multiprocessing import Manager
manager = Manager()
a = manager.list([i for i in range(size)])
print 'test shared manager list'
tranverse(a)


from multiprocessing.sharedctypes import RawArray
a = RawArray( 'i', [i for i in range(size)] )
print 'test sharedctypes list in main process'
tranverse(a)

from multiprocessing import Process
ps = [Process(target=tranverse, args=(a, )) for i in range(8)]
print 'test sharedctypes list in subprocess'
for p in ps:
    p.start()
for p in ps:
    p.join()

参考:
http://hi.baidu.com/%B1%D8%BC%C7%CE%B4%B6%C1/blog/item/f47e99d5cf0edfc051da4b8b.html
http://blogold.chinaunix.net/u3/108641/showart_2267237.html
http://www.rainsts.net/article.asp?id=1018

posted @ 2011-03-14 10:17  dkcndk  阅读(34369)  评论(0编辑  收藏  举报