Многопроцессорность Python с несколькими блокировками медленнее, чем с одной блокировкойPython

Программы на Python
Ответить Пред. темаСлед. тема
Anonymous
 Многопроцессорность Python с несколькими блокировками медленнее, чем с одной блокировкой

Сообщение Anonymous »

Я провожу эксперименты с многопроцессорностью в Python. Я написал код, который требует одновременной модификации трех разных переменных (dict, float и int), общих для разных процессов. Мое понимание работы блокировки подсказывает мне, что если у меня есть три разные общие переменные, будет более эффективно назначить блокировку каждой из них. В конце концов, почему процесс 2 должен ждать изменения переменной A только потому, что процесс 1 модифицирует переменную B? Для меня имеет смысл, что если вам нужно заблокировать переменную B, то A все равно должна быть доступна другим процессам.
Я запускаю два игрушечных примера ниже, основанных на реальной программе, которую пишу, и, к моему удивлению, код работает быстрее с одной блокировкой!
Одиночная блокировка: 2,1 секунды

Код: Выделить всё

import multiprocessing as mp
import numpy as np
import time

class ToyClass:
def __init__(self, shared_a, shared_b):
self.a = shared_a
self.b = shared_b

def update_a(self, key, n, lock):
with lock:
if key not in self.a:
self.a[key] = np.zeros(4)
self.a[key][n] += 1

def update_b(self, lock):
with lock:
self.b.value = max(0.1, self.b.value - 0.01)

def run_episode(toy, counter, lock):
key = np.random.randint(100)
n = np.random.randint(4)
toy.update_a(key, n, lock)
toy.update_b(lock)
with lock:
counter.value += 1

if __name__ == "__main__":
num_episodes = 1000
num_processes = 4

t0 = time.time()

with mp.Manager() as manager:
shared_a = manager.dict()
shared_b = manager.Value('d', 0)
counter = manager.Value('i', 0)

toy = ToyClass(shared_a=shared_a, shared_b=shared_b)

# Single lock
lock = manager.Lock()

pool = mp.Pool(processes=num_processes)

for _ in range(num_episodes):
pool.apply_async(run_episode, args=(toy, counter, lock))

pool.close()
pool.join()

tf = time.time()

print(f"Time to compute single lock: {tf - t0} seconds")
Множественные блокировки: 2,85 секунды!

Код: Выделить всё

import multiprocessing as mp
import numpy as np
import time

class ToyClass:  ## Same definition as for single lock
def __init__(self, shared_a, shared_b):
self.a = shared_a
self.b = shared_b

def update_a(self, key, n, lock):
with lock:
if key not in self.a:
self.a[key] = np.zeros(4)
self.a[key][n] += 1

def update_b(self, lock):
with lock:
self.b.value = max(0.1, self.b.value - 0.01)

def run_episode(toy, counter, lock_a, lock_b, lock_count):
key = np.random.randint(100)
n = np.random.randint(4)
toy.update_a(key, n, lock_a)
toy.update_b(lock_b)
with lock_count:
counter.value += 1

if __name__ == "__main__":
num_episodes = 1000
num_processes = 4

t0 = time.time()

with mp.Manager() as manager:
shared_a = manager.dict()
shared_b = manager.Value('d', 0)
counter = manager.Value('i', 0)

toy = ToyClass(shared_a=shared_a, shared_b=shared_b)

# 3 locks for 3 shared variables
lock_a = manager.Lock()
lock_b = manager.Lock()
lock_count = manager.Lock()

pool = mp.Pool(processes=num_processes)

for _ in range(num_episodes):
pool.apply_async(run_episode, args=(toy, counter, lock_a, lock_b, lock_count))

pool.close()
pool.join()

tf = time.time()

print(f"Time to compute multi-lock: {tf - t0} seconds")
Что мне здесь не хватает? Существуют ли вычислительные затраты при переключении между блокировками, которые перевешивают любую потенциальную выгоду? Это всего лишь флаги, как такое может быть?
Примечание. Я знаю, что код работает намного быстрее при использовании одного процесса/потока, но это часть эксперимента. именно для того, чтобы понять недостатки многопроцессорной обработки.

Подробнее здесь: https://stackoverflow.com/questions/790 ... ingle-lock
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «Python»