在不复制的情况下在进程之间共享 gmpy2 多精度整数
sharing gmpy2 multi-precision integer between processes without copying
是否可以在进程(由多进程创建)之间共享 gmpy2 多精度整数 (https://pypi.python.org/pypi/gmpy2) 而无需在内存中创建副本?
每个整数大约有 750,000 位。整数不被进程修改。
谢谢。
更新:测试代码如下。
我会尝试以下未经测试的方法:
使用 Python 的 mmap
库创建内存映射文件。
使用gmpy2.to_binary()
将gmpy2.mpz
实例转换为二进制字符串。
将二进制字符串的长度和二进制字符串本身写入内存映射文件。为了允许随机访问,您应该以固定值的倍数开始每次写入,在您的情况下为 94000。
用您的所有值填充内存映射文件。
然后在每个进程中,使用gmpy2.from_binary()
从内存映射文件中读取数据。
您需要读取二进制字符串的长度和二进制字符串本身。您应该能够将内存映射文件中的切片直接传递给 gmpy2.from_binary()
.
我可能更简单地为内存映射文件中每个字节字符串的位置创建一个 (start, end)
值列表,然后将该列表传递给每个进程。
更新:这是一些示例代码,已在 Linux 和 Python 3.4.
上进行了测试
import mmap
import struct
import multiprocessing as mp
import gmpy2
# Number of mpz integers to place in the memory buffer.
z_count = 40000
# Maximum number of bits in each integer.
z_bits = 750000
# Total number of bytes used to store each integer.
# Size is rounded up to a multiple of 4.
z_size = 4 + (((z_bits + 31) // 32) * 4)
def f(instance):
global mm
s = 0
for i in range(z_count):
mm.seek(i * z_size)
t = struct.unpack('i', mm.read(4))[0]
z = gmpy2.from_binary(mm.read(t))
s += z
print(instance, z % 123456789)
def main():
global mm
mm = mmap.mmap(-1, z_count * z_size)
rs = gmpy2.random_state(42)
for i in range(z_count):
z = gmpy2.mpz_urandomb(rs, z_bits)
b = gmpy2.to_binary(z)
mm.seek(i * z_size)
mm.write(struct.pack('i', len(b)))
mm.write(b)
ctx = mp.get_context('fork')
pool = ctx.Pool(4)
pool.map_async(f, range(4))
pool.close()
pool.join()
if __name__ == '__main__':
main()
是否可以在进程(由多进程创建)之间共享 gmpy2 多精度整数 (https://pypi.python.org/pypi/gmpy2) 而无需在内存中创建副本? 每个整数大约有 750,000 位。整数不被进程修改。
谢谢。
更新:测试代码如下。
我会尝试以下未经测试的方法:
使用 Python 的 mmap
库创建内存映射文件。
使用gmpy2.to_binary()
将gmpy2.mpz
实例转换为二进制字符串。
将二进制字符串的长度和二进制字符串本身写入内存映射文件。为了允许随机访问,您应该以固定值的倍数开始每次写入,在您的情况下为 94000。
用您的所有值填充内存映射文件。
然后在每个进程中,使用gmpy2.from_binary()
从内存映射文件中读取数据。
您需要读取二进制字符串的长度和二进制字符串本身。您应该能够将内存映射文件中的切片直接传递给 gmpy2.from_binary()
.
我可能更简单地为内存映射文件中每个字节字符串的位置创建一个 (start, end)
值列表,然后将该列表传递给每个进程。
更新:这是一些示例代码,已在 Linux 和 Python 3.4.
上进行了测试import mmap
import struct
import multiprocessing as mp
import gmpy2
# Number of mpz integers to place in the memory buffer.
z_count = 40000
# Maximum number of bits in each integer.
z_bits = 750000
# Total number of bytes used to store each integer.
# Size is rounded up to a multiple of 4.
z_size = 4 + (((z_bits + 31) // 32) * 4)
def f(instance):
global mm
s = 0
for i in range(z_count):
mm.seek(i * z_size)
t = struct.unpack('i', mm.read(4))[0]
z = gmpy2.from_binary(mm.read(t))
s += z
print(instance, z % 123456789)
def main():
global mm
mm = mmap.mmap(-1, z_count * z_size)
rs = gmpy2.random_state(42)
for i in range(z_count):
z = gmpy2.mpz_urandomb(rs, z_bits)
b = gmpy2.to_binary(z)
mm.seek(i * z_size)
mm.write(struct.pack('i', len(b)))
mm.write(b)
ctx = mp.get_context('fork')
pool = ctx.Pool(4)
pool.map_async(f, range(4))
pool.close()
pool.join()
if __name__ == '__main__':
main()