Как выделить разделяемую память так, чтобы записи в дочернем процессе были видны родительскому процессу? - PullRequest
0 голосов
/ 11 июля 2019

Справочная информация: Я пишу программу, которая считывает видеокадры с нескольких камер одновременно.Я хотел бы иметь 1 процесс, который выполняет чтение кадров и 2-й процесс, который записывает эти кадры на диск.Я пытался определить лучший способ (в Python 3.6) сделать фреймы в процессе «чтения» доступными для процесса «записи» для сохранения.Я попал в общую память как лучший вариант.

Проблема: Когда я выделяю общую память для обоих процессов, дочерний процесс не видит изменений, которые родительский процесс вносит в пространство общей памяти.

Предыдущее усилие: Я пробовал метод, предложенный Копируются ли общие данные только для чтения в разные процессы для многопроцессорной обработки? .Однако вставка этого кода непосредственно в Atom и попытка запустить его под Python 2.7 или Python 3.6 не дает того же результата, который дает связанный ответ (т. Е. Родительский процесс не видит изменений, сделанных my_func в дочернем процессе)

Примечание:

import multiprocessing
import ctypes
import numpy as np

shared_array_base = multiprocessing.Array(ctypes.c_double, 10*10)
shared_array = np.ctypeslib.as_array(shared_array_base.get_obj())
shared_array = shared_array.reshape(10, 10)

# Parallel processing
def my_func(i, def_param=shared_array):
    shared_array[i,:] = i

if __name__ == '__main__':
    pool = multiprocessing.Pool(processes=4)
    pool.map(my_func, range(10))

    print shared_array

1 Ответ

0 голосов
/ 12 июля 2019

играет с чем-то, что должно быть совместимо как с Unix, так и с Windows. Первой идеей, которую я придумал, является использование файлов с отображенной памятью, поскольку это в основном механизм разделяемой памяти

с ними довольно легко работать под Python. например, вот функция для создания такого массива:

import numpy as np
from ctypes import sizeof, c_double
from mmap import mmap, ACCESS_DEFAULT

def shared_array(
    shape, path, mode='rb', *,
    dtype=c_double, access=ACCESS_DEFAULT
):
    for n in reversed(shape):
        dtype *= n
    with open(path, mode) as fd:
        if fd.writable():
            size = fd.seek(0, 2)
            if size < sizeof(dtype):
                fd.truncate(sizeof(dtype))
        buf = mmap(fd.fileno(), sizeof(dtype), access=access)
    return np.ctypeslib.as_array(
        dtype.from_buffer(buf)
    )

т.е. создать «разделяемый массив NumPy» с заданной формой (т. е. (len,) или (rows, cols)), который появляется в файловой системе по заданному пути и с доступом, предоставленным mode (т. е. rb только для чтения, r+b это читать, писать).

это можно использовать с кодом вроде:

from multiprocessing import Pool, set_start_method

def fn(shape, path):
    array = shared_array(shape, path, 'r+b')
    np.fill_diagonal(array, 42)


def main():
    shape = (5, 10)
    path = 'tmp.buffer'
    array = shared_array(shape, path, 'w+b')
    with Pool() as pool:
        pool.apply(fn, (shape, path))
    print(array)


if __name__ == '__main__':
    set_start_method('spawn')
    main()

Я использую Linux, поэтому явно установил процесс в стиле Windows spawn ing style

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...