Предадените идеи за проекти са < 10
Към момента преподавателския екип е по-многоброен от изявилите желание да завършат курса в редовната сесия
Крания срок е тази неделя, не се мотайте
Ама все пак се постарайте
Идеите пратени по мейл не важат
ОК е да copy-paste-нете мейла си като решение на задачата
Ще имате и истинско домашно, за да не страдате.
Когато две изчисления се случват едновременно
Когато две изчисления нямат ясно дефинирана последователност на изпълнение.
Предварително знаем, че:
Няма как предварително да знаем
Това, за което повечето хора си мислят, когато им говориш за конкурентност.
Две изчисления, които реално се изпълняват едновременно
Предполага наличието на много ядра/процесори, така че няколко задачи наистина да вървят паралелно
Един python процес винаги таботи върху едно ядро
Досадно е, но уви спестява един ред други проблеми
Възможно е дори реферирането на променлива в няколко нишки едновременно да създаде проблем(защо?)
Как (unixy) операционна система реализира паралелизъм
#include <stdio.h>
int main()
{
printf("before\n");
if (fork())
printf("father\n");
else
printf("son\n");
printf("both\n");
}
before
son
both
father
both
import os
print("before")
if os.fork():
print("father")
else:
print("son")
print("both")
import os
import time
def log(msg): print("\n* " + msg)
orders = 0
while True:
order = input('Enter order: ')
if not order: continue
if order in ('q', 'x', 'quit', 'exit'): break
pid = os.fork()
if pid == 0:
time.sleep(3)
log("Order '{0}' is ready!".format(order))
break
else:
log("Roger that '{0}'({1}). Please, wait.".format(order, orders))
orders += 1
import os
pid = os.fork()
if pid == 0:
os.execlp('date', 'date')
else:
status = os.wait()
print("Father: son has finished {0}".format(status))
можем да ползваме и сигнали import signal
Против:
За:
даваме функция с параметри към нея
или
import threading
def f(name):
print("Hello from {0}".format(name))
thread = threading.Thread(target=f, args=('Bob',))
thread.start()
thread.join()
import threading
import time
orders = 0
class Chef(threading.Thread):
def __init__(self, order):
self.order = order
threading.Thread.__init__(self)
def run(self):
time.sleep(3)
log("Order '{0}' is ready!".format(self.order))
while True:
order = input('Enter order: ')
if not order: continue
if order in ('q', 'x', 'quit', 'exit'): break
chef = Chef(order)
chef.start()
log("Roger that '{0}'. Please, wait in quiet desperation.".format(order))
orders += 1
import random, time, threading
taken = False
class Philosopher(threading.Thread):
def __init__(self, name):
super().__init__(); self.name = name
def log(self, msg): print("{0}: {1}".format(self.name, msg))
def eat(self): time.sleep(random.random())
def ponder(self): time.sleep(random.random())
def refresh(self):
global taken
self.log("Please excuse me...");
while taken: pass;
taken = True; self.log("--> (entered the bathroom)")
time.sleep(random.random())
taken = False; self.log("<-- (left the bathroom)")
def run(self):
while True:
self.eat(); self.ponder(); self.refresh()
import random, time, threading
bathroom = threading.Lock()
class Philosopher(threading.Thread):
def __init__(self, name):
super().__init__(); self.name = name
def log(self, msg): print("{0}: {1}".format(self.name, msg))
def eat(self): time.sleep(random.random())
def ponder(self): time.sleep(random.random())
def refresh(self):
self.log("Please excuse me...")
bathroom.acquire(); self.log("--> (entered the bathroom)")
time.sleep(random.random())
bathroom.release(); self.log("<-- (left the bathroom)")
def run(self):
while True:
self.eat(); self.ponder(); self.refresh()
with
ни се гарантира викането на acquire()
преди и на release()
след блокаwith bathroom:
self.log("--> (entered the bathroom)")
time.sleep(random.random())
self.log("<-- (left the bathroom)")
А aко има повече от една тоалетна в сградата?
Или още по-добре
import threading, random, time
ovens = threading.Semaphore(5)
class WaiterChef(threading.Thread):
def __init__(self, name):
super(WaiterChef, self).__init__()
self.name = name
def run(self):
while True:
print("...({0}) waiting for an oven".format(self.name))
ovens.acquire()
print("--> ({0}) Cooking...".format(self.name))
time.sleep(random.random() * 10)
ovens.release()
print("<-- ({0}) Serving...".format(self.name))
time.sleep(random.random() * 4)
for _ in range(0, 10):
WaiterChef(_).start()
multiprocessing модулът
from multiprocessing import Process
import os
def info(title):
print(title)
print('module name:', __name__)
print('parent process:', os.getppid())
print('process id:', os.getpid())
def f(name):
info('function f')
print('hello', name)
if __name__ == '__main__':
info('main line')
p = Process(target=f, args=('bob',))
p.start()
p.join()
from multiprocessing import Process, Value
def f(n):
# work
v = n.value
for x in range(0, 30000): x=x+2
n.value = v + 1
# work
if __name__ == '__main__':
num = Value('i', 0)
processes = [Process(target=f, args=(num,)) for i in range(0, 10)]
for p in processes:
p.start()
for p in processes:
p.join()
print(num.value)
Lock - осигурява че само един процес може да го държи
from multiprocessing import Process, Value, Lock
def f(n, lock):
# work
lock.acquire()
v = n.value
for x in range(0, 30000): x=x+2
n.value = v + 1
lock.release()
# work
if __name__ == '__main__':
num = Value('i', 0)
lock = Lock()
processes = [Process(target=f, args=(num, lock)) for i in range(0, 10)]
for p in processes:
p.start()
for p in processes:
p.join()
print(num.value)
Позволява създаването на споделени обекти
from multiprocessing import Process, Manager
def f(d, l):
d[1] = '1'
d['2'] = 2
d[0.25] = None
l.reverse()
if __name__ == '__main__':
manager = Manager()
d, l = manager.dict(), manager.list(range(10))
p = Process(target=f, args=(d, l))
p.start()
p.join()
print(d, l)
{0.25: None, 1: '1', '2': 2}
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]