← Назад к вопросам

Что такое Shared memory?

1.8 Middle🔥 131 комментариев
#Python Core

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

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.

Что такое Shared memory? | PrepBro