2016-05-08 3 views
0

Можно ли совместно использовать целые числа gmpy2 multiprecision (https://pypi.python.org/pypi/gmpy2) между процессами (созданными с помощью многопроцессорности) без создания копий в памяти? Каждое целое число имеет около 750 000 бит. Целые числа не изменяются процессами.Совместное использование многоточечного целого числа gmpy2 между процессами без копирования

спасибо.

ответ

0

Обновление: Протестирован код ниже.

Я хотел бы попробовать следующий непроверенный подход:

Создание памяти отображенный файл с помощью 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() 
+0

Позвольте мне попробовать и получить время. Я просто попробовал многопроцессорный менеджер. Это кажется медленным. – rxu

+0

, что функция from_binary работает медленно. можно ли обрабатывать весь mmap как один xmpz. Затем, в начале каждого процесса, весь mmap интерпретируется как один xmpz без копирования содержимого mmap. После этого мы можем выполнять операции на срезах xmpz. – rxu

+0

Текущая реализация to_binary()/from_binary() предназначена для нейтрализации платформы. Компромисс - это производительность. Я думал о более быстрых версиях, но, вероятно, потребуется некоторое время, прежде чем я смогу работать над этим. – casevh

Смежные вопросы