Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Shared Memory: Механизм общей памяти для межпроцессного взаимодействия
Shared memory — это механизм межпроцессного взаимодействия (IPC), при котором несколько процессов получают доступ к одному и тому же участку памяти. Это позволяет процессам обмениваться данными без копирования, что делает такой способ очень эффективным.
Концепция
Обычные процессы:
Процесс 1 Процесс 2 Процесс 3
┌─────────┐ ┌─────────┐ ┌─────────┐
│ Память │ │ Память │ │ Память │
│ изолир. │ │ изолир. │ │ изолир. │
└─────────┘ └─────────┘ └─────────┘
Для обмена нужно копировать данные через сокеты/трубы
С Shared Memory:
Процесс 1 Процесс 2 Процесс 3
┌──────────┐ ┌──────────┐ ┌──────────┐
│ Память │ │ Память │ │ Память │
└────┬─────┘ └────┬─────┘ └────┬─────┘
└──────────────────┼──────────────┘
Shared Memory Region (общая память)
Все процессы видят одни и те же данные без копирования.
Как это работает
import multiprocessing
from multiprocessing import shared_memory
import numpy as np
# Процесс 1: Создает shared memory
shm = shared_memory.SharedMemory(create=True, size=1000)
shared_array = np.ndarray((100,), dtype=np.int32, buffer=shm.buf)
# Записываем данные
shared_array[:] = np.arange(100)
print(f"Shared memory ID: {shm.name}")
# Передаем shm.name другим процессам
# Процесс 2: Подключается к shared memory
shm2 = shared_memory.SharedMemory(name=shm.name) # Подключаемся по имени
shared_array2 = np.ndarray((100,), dtype=np.int32, buffer=shm2.buf)
# Видим те же данные
print(shared_array2[:10]) # [0 1 2 3 4 5 6 7 8 9]
# Если один процесс изменит — другой тоже увидит
shared_array2[0] = 999
# В Процессе 1: shared_array[0] теперь тоже 999
# Очистка
shm.close()
shm.unlink() # Удалить сегмент памяти
Практический пример: многопроцессная обработка
import multiprocessing
from multiprocessing import shared_memory
import numpy as np
import time
def worker(shm_name, worker_id):
"""Рабочий процесс читает и обновляет shared memory"""
# Подключаемся к существующему shared memory
shm = shared_memory.SharedMemory(name=shm_name)
counter = np.ndarray((1,), dtype=np.int32, buffer=shm.buf)
for i in range(5):
counter[0] += 1 # Инкрементируем счетчик
print(f"Worker {worker_id}: counter = {counter[0]}")
time.sleep(0.1)
shm.close()
if __name__ == "__main__":
# Основной процесс: создает shared memory
shm = shared_memory.SharedMemory(create=True, size=4) # 1 int32
counter = np.ndarray((1,), dtype=np.int32, buffer=shm.buf)
counter[0] = 0
print(f"Main: Created shared memory {shm.name}")
# Запускаем 3 рабочих процесса
processes = []
for i in range(3):
p = multiprocessing.Process(target=worker, args=(shm.name, i))
p.start()
processes.append(p)
# Ждем завершения
for p in processes:
p.join()
print(f"Final counter: {counter[0]}") # 15 (5 * 3)
# Очистка
shm.close()
shm.unlink()
В этом примере все процессы пишут в один счетчик. Без shared memory пришлось бы синхронизировать данные через очереди или файлы.
Плюсы shared memory
✓ ОЧЕНЬ быстро — нет копирования данных
✓ Минимальные накладные расходы
✓ Подходит для больших данных (видео, матрицы, изображения)
✓ Естественно для многопроцессной обработки
✓ Работает между процессами на одной машине
Минусы и проблемы
✗ RACE CONDITIONS — если два процесса пишут одновременно
✗ DEADLOCKS — при неправильной синхронизации
✗ Нужна синхронизация (Lock, Semaphore)
✗ Сложнее отладить
✗ ОС сама очищает только при перезагрузке
Race condition пример
# ОПАСНО! Race condition
def worker_unsafe(shm_name):
shm = shared_memory.SharedMemory(name=shm_name)
counter = np.ndarray((1,), dtype=np.int32, buffer=shm.buf)
# Проблема: прочитаем-изменим-запишем не атомарно!
for _ in range(1000):
temp = counter[0] # Прочитали
counter[0] = temp + 1 # Написали
# Если два процесса делают это одновременно,
# конечный результат будет меньше 2000!
# ПРАВИЛЬНО! С Lock
from multiprocessing import Lock
def worker_safe(shm_name, lock):
shm = shared_memory.SharedMemory(name=shm_name)
counter = np.ndarray((1,), dtype=np.int32, buffer=shm.buf)
for _ in range(1000):
with lock: # Только один процесс за раз
counter[0] += 1
Сравнение механизмов IPC
Особенность Shared Memory Pipes Sockets Queue
─────────────────────────────────────────────────────────
Скорость ★★★★★ ★★★ ★★ ★★★
Просто писать ★★ ★★★★ ★★ ★★★★
Межмашинный обмен ✗ ✗ ✓ ✓
Синхронизация Сложная Нет Нет Встроенная
Подходит для Матрицы, Текст Сеть Задачи
видео обработки
Реальный пример: видеопроцессинг
import multiprocessing
from multiprocessing import shared_memory, Lock
import numpy as np
from PIL import Image
def process_frame(shm_name, lock, frame_id):
"""Применяет фильтр к кадру в shared memory"""
shm = shared_memory.SharedMemory(name=shm_name)
# Видео 1920x1080x3 (RGB) = 6.2MB
frames = np.ndarray((100, 1080, 1920, 3), dtype=np.uint8, buffer=shm.buf)
with lock: # Синхронизируем доступ
# Применяем фильтр (например, уменьшение яркости)
frames[frame_id] = frames[frame_id] * 0.8
print(f"Processed frame {frame_id}")
shm.close()
if __name__ == "__main__":
# Создаем видеобуфер (100 кадров x 1920x1080 RGB)
shm = shared_memory.SharedMemory(
create=True,
size=100 * 1920 * 1080 * 3 # ~600MB
)
frames = np.ndarray((100, 1080, 1920, 3), dtype=np.uint8, buffer=shm.buf)
# Заполняем тестовыми данными
frames[:] = np.random.randint(0, 256, frames.shape, dtype=np.uint8)
lock = Lock()
# Запускаем 4 процесса для параллельной обработки
processes = []
for i in range(4):
for frame_id in range(i * 25, (i + 1) * 25):
p = multiprocessing.Process(
target=process_frame,
args=(shm.name, lock, frame_id)
)
p.start()
processes.append(p)
for p in processes:
p.join()
print("Video processing complete")
shm.close()
shm.unlink()
Этот пример показывает, почему shared memory критична для видеопроцессинга — копирование 600MB между процессами было бы катастрофой для производительности.
Когда использовать shared memory
✓ Обработка больших массивов данных (NumPy)
✓ Видеопроцессинг, обработка изображений
✓ Высоконагруженные многопроцессные приложения
✓ Когда скорость критична
✗ Простой обмен небольшими сообщениями (используй Queue)
✗ Когда нужна работа между машинами (используй sockets)
✗ Если не уверен в синхронизации (используй более высокоуровневые абстракции)
Резюме
Shared memory — это механизм, при котором несколько процессов обращаются к одному участку памяти без копирования. Это очень быстро, но требует правильной синхронизации через Lock/Semaphore. Ideally для обработки больших данных (видео, матрицы) в Python используется через multiprocessing.shared_memory с NumPy.