mpi4py 中的 memory 对象及内存操作

上一篇中我们介绍了 mpi4py 中的客户端-服务器编程方法,下面我们将介绍 mpi4py 中的 memory 对象及内存操作。

Python 是一种比较高级的动态编程语言,通过其提供的高级对象和语法,我们一般不需要直接同底层的内存操作打交道,比如说,在 Python 中,我们一般不会如在 C/C++ 等语言中一样先分配内存区域,然后使用分配的内存,使用完后再释放内存,Python 会为我们自动进行内存管理,并在合适的时候自动进行垃圾回收,以释放一些不再使用的对象所占用的内存空间。

MPI 标准一般是用像 C 这样较低级的语言实现的,在 MPI 的很多操作中都涉及对内存的直接使用,如消息传递的内存缓冲区,单边通信中的动态窗口创建及内存加载/卸载等,因此 MPI 中提供了若干对内存的操作和管理函数。

mpi4py 对 MPI 标准实现进行了封装,提供了比较高级的 Python 使用接口,使我们能够非常方便地在 Python 语言中以 Python 的高级语法形式使用 MPI。使用 mpi4py,对内存的直接底层操作是应该尽量避免的,因为这并不符合 Python 的编程哲学和编程方式。因此,mpi4py 提供了 MPI.memory 对象,封装和隐藏了对内存的底层操作,为我们提供了比较高级的符合 Python 编程方式的方法接口。如果涉及到内存操作,我们应该尽量使用 MPI.memory 对象。当然,mpi4py 也提供了若干内存操作函数,这些是对 MPI 标准中对应函数的直接封装和调用。

MPI.memory 对象

方法

MPI.memory.frombuffer(obj, bint readonly=False)

MPI.memory 类的静态方法,由参数 obj 的缓冲区创建并返回一个 MPI.memory 对象,readonly 指定创建的 MPI.memory 对象是否是只读的。obj 必须是实现了缓冲区协议(buffer protocal)的对象。

MPI.memory.fromaddress(address, nbytes, bint readonly=False)

MPI.memory 类的静态方法,由内存地址 address 开始的连续 nbytes 字节的一块内存区创建并返回一个 MPI.memory 对象,readonly 指定创建的 MPI.memory 对象是否是只读的。

MPI.memory.tobytes(self)

将该 MPI.memory 对象所包含的内存区的数据作为一个 byte string 返回。

MPI.memory.release(self)

释放该 MPI.memory 对象所包含的内存区。

MPI.memory.__len__(self)

返回该 MPI.memory 对象所包含的内存区的大小(以字节为单位计算),对一个没有包含内存区的 MPI.memory 对象返回 0。

MPI.memory.__getitem__(self, object item)

通过 m[index] 操作返回当前 MPI.memory 对象内存缓冲区 index 处的数据。

MPI.memory.__setitem__(self, object item, object value)

通过 m[index] = value 操作设置当前 MPI.memory 对象内存缓冲区 index 处的数据为 value。

属性

MPI.memory.address

当前 MPI.mempry 对象内存缓冲区的地址。

MPI.memory.nbytes

当前 MPI.mempry 对象内存缓冲区的大小(以字节为单位计算)。

MPI.memory.readonly

当前 MPI.mempry 对象内存缓冲区是否为只读。

其它内存操作方法

MPI.Alloc_mem(Aint size, Info info=INFO_NULL)

在内存中分配 size 大小(以字节为单位计算)的区域,返回由分配区域创建的 MPI.memory 对象。

MPI.Get_address(location)

获取并返回内存中某个位置 location 的地址。

MPI.Free_mem(mem)

释放由 MPI.Alloc_mem 分配的内存区。注意:只能用该函数释放由 MPI.Alloc_mem 分配的内存空间,如果用该函数释放一个不是由 MPI.Alloc_mem 分配的 MPI.memory 对象则会出错。

缓冲区协议及 memoryview

MPI.memory 对象实现了 Python 的缓冲区协议(buffer protocal, PEP 3118),因此可以使用 Python 的 buffer 函数获取其缓冲区,或者通过 memoryview 对象来获取和使用其内存缓冲区中的数据(可以避免额外的复制操作)。目前,Python 已经不推荐使用 buffer 函数,将来可能会废弃 buffer 函数,因此建议使用 memoryview 对象。它们的函数/方法接口如下:

buffer(object[, offset[, size]])

class memoryview(obj)

memoryview.tobytes()

memoryview.tolist()

另外 memoryview 对象有属性 format,itemsize,shape,ndim,strides,readonly。

buffer 函数和 memoryview 对象都是 Python 内置的对象,读者可以参考 Python 的相关文档,在此不作进一步介绍。

例程

下面给出使用例程。

# mem.py

"""
Demonstrates memory operations.

Run this with 1 processes like:
$ mpiexec -n 1 python mem.py
or
$ python mem.py
"""

import numpy as np
from mpi4py import MPI


comm = MPI.COMM_WORLD
rank = comm.rank

# create a MPI.memory object from a byte string
mem = MPI.memory.frombuffer(b"abc", readonly=True)
print 'mem.address:', mem.address
print 'mem.nbytes:', mem.nbytes
print 'mem.readonly:', mem.readonly
# get the read-only buffer of mem
buf = buffer(mem)
print 'buffer:', buf
# create a memory view of mem
mv = memoryview(mem)
print 'mv[0]:', mv[0]
try:
    # try to modify a readonly buffer
    mv[0] = 'x'
except TypeError as e:
    print e
# release the memory object
mem.release()

print

# create a MPI.memory object from a byte array, which stands for ASCII code a, b, c
mem = MPI.memory.frombuffer(bytearray([97, 98, 99]), readonly=False)
addr = mem.address
nbytes = mem.nbytes
# create a new MPI.memory object which shares the memory of mem
mem1 = MPI.memory.fromaddress(addr, nbytes, readonly=False)
# get the read-only buffer of mem
buf = buffer(mem)
print 'buffer:', buf
try:
    # try to change the read-only buffer object
    buf[0] = b'x'
except TypeError as e:
    print e
# create a memory view of mem
mv = memoryview(mem)
# create a memory view of mem1
mv1 = memoryview(mem1)
print 'before change: mv[0] = %s, mv1[0] = %s' % (mv[0], mv1[0])
# change mv[0]
mv[0] = 'x'
print 'after change: mv[0] = %s, mv1[0] = %s' % (mv[0], mv1[0])
# release the memory object
mem.release()

print

# allocate a memory of 40 bytes, return a MPI.memory object
mem = MPI.Alloc_mem(10*4)
print 'len(mem):', len(mem)
print 'mem.address:', MPI.Get_address(mem)
# create a numpy array from the allocated memory
# NOTE: use copy = False here to avoid the copy
buf = np.array(mem, dtype='B', copy=False)
# cast to be int array
npary = np.ndarray(buffer=buf, dtype='i', shape=(10,))
# now you can operate the memory buffer by the usual numpy array operations
npary[:] = np.arange(10)
print 'npary.tobytes:', npary.tobytes()
# release the memory object
MPI.Free_mem(mem)
print 'len(mem) after free:', len(mem)

运行结果如下:

$ python mem.py
mem.address: 139804154439796
mem.nbytes: 3
mem.readonly: True
buffer: abc
mv[0]: a
cannot modify read-only memory

buffer: abc
buffer is read-only
before change: mv[0] = a, mv1[0] = a
after change: mv[0] = x, mv1[0] = x

len(mem): 40
mem.address: 50202096
npary.tobytes: �������  
len(mem) after free: 0

以上介绍了 mpi4py 中的 memory 对象及内存操作,在下一篇中我们将介绍 mpi4py 中的简单并行 I/O 操作。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 200,302评论 5 470
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,232评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 147,337评论 0 332
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,977评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,920评论 5 360
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,194评论 1 277
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,638评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,319评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,455评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,379评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,426评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,106评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,696评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,786评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,996评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,467评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,043评论 2 341

推荐阅读更多精彩内容