Обновление: Протестирован код ниже.
Я хотел бы попробовать следующий непроверенный подход:
Создание памяти отображенный файл с помощью mmap
библиотеки Python.
Используйте 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()
Позвольте мне попробовать и получить время. Я просто попробовал многопроцессорный менеджер. Это кажется медленным. – rxu
, что функция from_binary работает медленно. можно ли обрабатывать весь mmap как один xmpz. Затем, в начале каждого процесса, весь mmap интерпретируется как один xmpz без копирования содержимого mmap. После этого мы можем выполнять операции на срезах xmpz. – rxu
Текущая реализация to_binary()/from_binary() предназначена для нейтрализации платформы. Компромисс - это производительность. Я думал о более быстрых версиях, но, вероятно, потребуется некоторое время, прежде чем я смогу работать над этим. – casevh