├── Chapter01 ├── __pycache__ │ └── do_something.cpython-35.pyc ├── classes.py ├── dir.py ├── do_something.py ├── file.py ├── flow.py ├── lists.py ├── multiprocessing_test.py ├── multithreading_test.py ├── serial_test.py ├── test.txt └── thread_and_processes.py ├── Chapter02 ├── Barrier.py ├── Condition.py ├── Event.py ├── MyThreadClass.py ├── MyThreadClass_lock.py ├── MyThreadClass_lock_2.py ├── Rlock.py ├── Semaphore.py ├── Thread_definition.py ├── Thread_determine.py ├── Thread_name_and_processes.py └── Threading_with_queue.py ├── Chapter03 ├── __pycache__ │ └── myFunc.cpython-35.pyc ├── communicating_with_pipe.py ├── communicating_with_queue.py ├── killing_processes.py ├── myFunc.py ├── naming_processes.py ├── process_in_subclass.py ├── process_pool.py ├── processes_barrier.py ├── run_background_processes.py ├── run_background_processes_no_daemons.py ├── spawning_processes.py └── spawning_processes_namespace.py ├── Chapter04 ├── alltoall.py ├── broadcast.py ├── deadLockProblems.py ├── gather.py ├── helloworld_MPI.py ├── pointToPointCommunication.py ├── reduction.py ├── scatter.py └── virtualTopology.py ├── Chapter05 ├── asyncio_and_futures.py ├── asyncio_coroutine.py ├── asyncio_event_loop.py ├── asyncio_task_manipulation.py └── concurrent_futures_pooling.py ├── Chapter06 ├── Celery │ ├── addTask.py │ └── addTask_main.py ├── Pyro4 │ ├── First Example │ │ ├── pyro_client.py │ │ └── pyro_server.py │ └── Second Example │ │ ├── __pycache__ │ │ └── chainTopology.cpython-35.pyc │ │ ├── chainTopology.py │ │ ├── client_chain.py │ │ ├── desktop.ini │ │ ├── server_chain_1.py │ │ ├── server_chain_2.py │ │ └── server_chain_3.py └── socket │ ├── addTask.py │ ├── addTask_main.py │ ├── client.py │ ├── client2.py │ ├── mytext.txt │ ├── received.txt │ ├── server.py │ └── server2.py ├── Chapter07 └── codes │ └── how to containerize a Python application │ ├── Dockerfile │ ├── dockerize.py │ └── requirements.txt ├── Chapter08 ├── Numba │ ├── matMulNumba.py │ ├── numba_cuda_detection.py │ └── reduceNumba.py ├── PyCUDA │ ├── dealingWithPycuda.py │ ├── heterogenousPycuda.py │ └── memManagementPycuda.py └── PyOpenCL │ ├── __pycache__ │ └── deviceInfoPyopencl.cpython-37.pyc │ ├── deviceInfoPyopencl.py │ ├── elementwisePyopencl.py │ ├── testApplicationPyopencl.py │ └── vectorSumPyopencl.py ├── Chapter09 └── codes chapter 9 debug and test │ ├── __pycache__ │ ├── testset.cpython-36.pyc │ └── testset1.cpython-36.pyc │ ├── nosetest.py │ ├── pdb │ ├── __pycache__ │ │ └── pdb_test.cpython-35.pyc │ ├── inside_code_to_debug_pdb.py │ ├── pdb_test.py │ ├── postmortem.py │ ├── unittest_fail.py │ └── using_python_interpreter_pdb.py │ ├── rpdb_code_example.py │ ├── simplicisticTest.py │ ├── testset.py │ ├── testset1.py │ ├── unittest_exception.py │ ├── unittest_truth.py │ └── winpdb_reborn_code_example.py ├── LICENSE └── README.md /Chapter01/__pycache__/do_something.cpython-35.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Python-Parallel-Programming-Cookbook-Second-Edition/a10f0b2ba69995a6a8697e68ae0b53a20f4c04c7/Chapter01/__pycache__/do_something.cpython-35.pyc -------------------------------------------------------------------------------- /Chapter01/classes.py: -------------------------------------------------------------------------------- 1 | class Myclass: 2 | common = 10 3 | def __init__ (self): 4 | self.myvariable = 3 5 | def myfunction (self, arg1, arg2): 6 | return self.myvariable 7 | 8 | instance = Myclass() 9 | print("instance.myfunction(1, 2)" , instance.myfunction(1, 2)) 10 | 11 | instance2 = Myclass() 12 | print("instance.common ",instance.common) 13 | print("instance2.common ",instance2.common) 14 | 15 | Myclass.common = 30 16 | 17 | print("instance.common ", instance.common) 18 | 19 | print("instance2.common ", instance2.common) 20 | 21 | instance.common = 10 22 | print("instance.common ", instance.common) 23 | 24 | print("instance2.common " , instance2.common) 25 | Myclass.common = 50 26 | 27 | print("instance.common ", instance.common) 28 | print("instance2.common " , instance2.common) 29 | 30 | class AnotherClass (Myclass): 31 | # The "self" argument is passed automatically 32 | # and refers to the class's instance, so you can set 33 | # instance variables as above, but from within the class. 34 | def __init__ (self, arg1): 35 | self.myvariable = 3 36 | print (arg1) 37 | 38 | instance = AnotherClass ("hello") 39 | print("instance.myfunction (1, 2) " , instance.myfunction (1, 2)) 40 | 41 | instance.test = 10 42 | print("instance.test " , instance.test) 43 | 44 | 45 | 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /Chapter01/dir.py: -------------------------------------------------------------------------------- 1 | # In this program, 2 | # we check if the number is positive or 3 | # negative or zero and 4 | # display an appropriate message 5 | 6 | num = 1 7 | 8 | # Try these two variations as well: 9 | # num = 0 10 | # num = -4.5 11 | 12 | if num > 0: 13 | print("Positive number") 14 | elif num == 0: 15 | print("Zero") 16 | else: 17 | print("Negative number") 18 | 19 | 20 | 21 | # Program to find the sum of all numbers stored in a list 22 | 23 | # List of numbers 24 | numbers = [6, 6, 3, 8, -3, 2, 5, 44, 12] 25 | 26 | # variable to store the sum 27 | sum = 0 28 | 29 | # iterate over the list 30 | for val in numbers: 31 | sum = sum+val 32 | 33 | # Output: The sum is 48 34 | print("The sum is", sum) 35 | 36 | -------------------------------------------------------------------------------- /Chapter01/do_something.py: -------------------------------------------------------------------------------- 1 | import random 2 | 3 | def do_something(count,out_list): 4 | for i in range(count): 5 | out_list.append(random.random()) 6 | 7 | -------------------------------------------------------------------------------- /Chapter01/file.py: -------------------------------------------------------------------------------- 1 | f = open ('test.txt', 'w') 2 | f.write ('first line of file \n') 3 | 4 | f.write ('second line of file \n') 5 | 6 | f.close() 7 | f = open ('test.txt') 8 | content = f.read() 9 | print (content) 10 | 11 | f.close() 12 | -------------------------------------------------------------------------------- /Chapter01/flow.py: -------------------------------------------------------------------------------- 1 | 2 | # IF 3 | 4 | # In this program, we check if the number is positive or negative or zero and 5 | # display an appropriate message 6 | 7 | num = 1 8 | if num > 0: 9 | print("Positive number") 10 | elif num == 0: 11 | print("Zero") 12 | else: 13 | print("Negative number") 14 | 15 | 16 | # FOR 17 | # Program to find the sum of all numbers stored in a list 18 | numbers = [6, 6, 3, 8, -3, 2, 5, 44, 12] 19 | sum = 0 20 | for val in numbers: 21 | sum = sum+val 22 | 23 | # Output: The sum is 48 24 | print("The sum is", sum) 25 | 26 | 27 | #WHILE 28 | # Program to add natural numbers upto sum = 1+2+3+...+n 29 | 30 | n = 10 31 | # initialize sum and counter 32 | sum = 0 33 | i = 1 34 | while i <= n: 35 | sum = sum + i 36 | i = i+1 # update counter 37 | 38 | # print the sum 39 | print("The sum is", sum) 40 | 41 | -------------------------------------------------------------------------------- /Chapter01/lists.py: -------------------------------------------------------------------------------- 1 | example = [1, ["another", "list"], ("a", "tuple")] 2 | example 3 | mylist = ["element 1", 2, 3.14] 4 | mylist 5 | mylist[0] = "yet element 1" 6 | print(mylist[0]) 7 | mylist[-1] = 3.15 8 | print (mylist[-1]) 9 | mydict = {"Key 1": "value 1", 2: 3, "pi": 3.14} 10 | print(mydict) 11 | mydict["pi"] = 3.15 12 | print(mydict["pi"]) 13 | mytuple = (1, 2, 3) 14 | print(mytuple) 15 | myfunc = len 16 | print (myfunc(mylist)) 17 | -------------------------------------------------------------------------------- /Chapter01/multiprocessing_test.py: -------------------------------------------------------------------------------- 1 | from do_something import * 2 | import time 3 | import multiprocessing 4 | 5 | 6 | if __name__ == "__main__": 7 | start_time = time.time() 8 | size = 10000000 9 | procs = 10 10 | jobs = [] 11 | for i in range(0, procs): 12 | out_list = list() 13 | process = multiprocessing.Process\ 14 | (target=do_something,args=(size,out_list)) 15 | jobs.append(process) 16 | 17 | for j in jobs: 18 | j.start() 19 | 20 | for j in jobs: 21 | j.join() 22 | 23 | print ("List processing complete.") 24 | end_time = time.time() 25 | print("multiprocesses time=", end_time - start_time) 26 | -------------------------------------------------------------------------------- /Chapter01/multithreading_test.py: -------------------------------------------------------------------------------- 1 | from do_something import * 2 | import time 3 | import threading 4 | 5 | if __name__ == "__main__": 6 | start_time = time.time() 7 | size = 10000000 8 | threads = 10 9 | jobs = [] 10 | for i in range(0, threads): 11 | out_list = list() 12 | thread = threading.Thread(target=do_something(size, out_list)) 13 | jobs.append(thread) 14 | for j in jobs: 15 | j.start() 16 | 17 | 18 | for j in jobs: 19 | j.join() 20 | 21 | print ("List processing complete.") 22 | end_time = time.time() 23 | print("multithreading time=", end_time - start_time) 24 | 25 | -------------------------------------------------------------------------------- /Chapter01/serial_test.py: -------------------------------------------------------------------------------- 1 | import time 2 | from do_something import * 3 | 4 | if __name__ == "__main__": 5 | start_time = time.time() 6 | size = 10000000 7 | n_exec = 10 8 | for i in range(0, n_exec): 9 | out_list = list() 10 | do_something(size, out_list) 11 | 12 | 13 | print ("List processing complete.") 14 | end_time = time.time() 15 | print("serial time=", end_time - start_time) 16 | -------------------------------------------------------------------------------- /Chapter01/test.txt: -------------------------------------------------------------------------------- 1 | first line of file 2 | second line of file 3 | -------------------------------------------------------------------------------- /Chapter01/thread_and_processes.py: -------------------------------------------------------------------------------- 1 | import os 2 | import time 3 | import threading 4 | import multiprocessing 5 | import random 6 | 7 | NUM_WORKERS = 10 8 | size = 10000000 9 | out_list = list() 10 | 11 | def do_something(count, out_list): 12 | for i in range(count): 13 | out_list.append(random.random()) 14 | """ 15 | #Serial 16 | start_time = time.time() 17 | for _ in range(NUM_WORKERS): 18 | do_something(size,out_list) 19 | end_time = time.time() 20 | print("Serial time=", end_time - start_time) 21 | """ 22 | 23 | #MultiThreading 24 | start_time = time.time() 25 | jobs = [] 26 | for i in range(0, NUM_WORKERS): 27 | thread = threading.Thread(target=do_something(size, out_list)) 28 | jobs.append(thread) 29 | for j in jobs: 30 | j.start() 31 | 32 | for j in jobs: 33 | j.join() 34 | 35 | print ("List processing complete.") 36 | end_time = time.time() 37 | print("threading time=", end_time - start_time) 38 | 39 | 40 | #MultiProcesses 41 | start_time = time.time() 42 | jobs = [] 43 | for i in range(0, NUM_WORKERS): 44 | process = multiprocessing.Process\ 45 | (target=do_something,args=(size,out_list)) 46 | jobs.append(process) 47 | 48 | for j in jobs: 49 | j.start() 50 | 51 | for j in jobs: 52 | j.join() 53 | 54 | print ("List processing complete.") 55 | end_time = time.time() 56 | print("processes time=", end_time - start_time) 57 | -------------------------------------------------------------------------------- /Chapter02/Barrier.py: -------------------------------------------------------------------------------- 1 | from random import randrange 2 | from threading import Barrier, Thread 3 | from time import ctime, sleep 4 | 5 | num_runners = 3 6 | finish_line = Barrier(num_runners) 7 | runners = ['Huey', 'Dewey', 'Louie'] 8 | 9 | def runner(): 10 | name = runners.pop() 11 | sleep(randrange(2, 5)) 12 | print('%s reached the barrier at: %s \n' % (name, ctime())) 13 | finish_line.wait() 14 | 15 | def main(): 16 | threads = [] 17 | print('START RACE!!!!') 18 | for i in range(num_runners): 19 | threads.append(Thread(target=runner)) 20 | threads[-1].start() 21 | for thread in threads: 22 | thread.join() 23 | print('Race over!') 24 | 25 | if __name__ == "__main__": 26 | main() 27 | -------------------------------------------------------------------------------- /Chapter02/Condition.py: -------------------------------------------------------------------------------- 1 | import logging 2 | import threading 3 | import time 4 | 5 | LOG_FORMAT = '%(asctime)s %(threadName)-17s %(levelname)-8s %(message)s' 6 | logging.basicConfig(level=logging.INFO, format=LOG_FORMAT) 7 | 8 | items = [] 9 | condition = threading.Condition() 10 | 11 | 12 | class Consumer(threading.Thread): 13 | def __init__(self, *args, **kwargs): 14 | super().__init__(*args, **kwargs) 15 | 16 | def consume(self): 17 | 18 | with condition: 19 | 20 | if len(items) == 0: 21 | logging.info('no items to consume') 22 | condition.wait() 23 | 24 | items.pop() 25 | logging.info('consumed 1 item') 26 | 27 | condition.notify() 28 | 29 | def run(self): 30 | for i in range(20): 31 | time.sleep(2) 32 | self.consume() 33 | 34 | 35 | class Producer(threading.Thread): 36 | def __init__(self, *args, **kwargs): 37 | super().__init__(*args, **kwargs) 38 | 39 | def produce(self): 40 | 41 | with condition: 42 | 43 | if len(items) == 10: 44 | logging.info('items produced {}. Stopped'.format(len(items))) 45 | condition.wait() 46 | 47 | items.append(1) 48 | logging.info('total items {}'.format(len(items))) 49 | 50 | condition.notify() 51 | 52 | def run(self): 53 | for i in range(20): 54 | time.sleep(0.5) 55 | self.produce() 56 | 57 | 58 | def main(): 59 | producer = Producer(name='Producer') 60 | consumer = Consumer(name='Consumer') 61 | 62 | producer.start() 63 | consumer.start() 64 | 65 | producer.join() 66 | consumer.join() 67 | 68 | 69 | if __name__ == "__main__": 70 | main() 71 | -------------------------------------------------------------------------------- /Chapter02/Event.py: -------------------------------------------------------------------------------- 1 | import logging 2 | import threading 3 | import time 4 | import random 5 | 6 | LOG_FORMAT = '%(asctime)s %(threadName)-17s %(levelname)-8s %(message)s' 7 | logging.basicConfig(level=logging.INFO, format=LOG_FORMAT) 8 | 9 | items = [] 10 | event = threading.Event() 11 | 12 | 13 | class Consumer(threading.Thread): 14 | def __init__(self, *args, **kwargs): 15 | super().__init__(*args, **kwargs) 16 | 17 | def run(self): 18 | while True: 19 | time.sleep(2) 20 | event.wait() 21 | item = items.pop() 22 | logging.info('Consumer notify: {} popped by {}'\ 23 | .format(item, self.name)) 24 | 25 | class Producer(threading.Thread): 26 | def __init__(self, *args, **kwargs): 27 | super().__init__(*args, **kwargs) 28 | 29 | def run(self): 30 | for i in range(5): 31 | time.sleep(2) 32 | item = random.randint(0, 100) 33 | items.append(item) 34 | logging.info('Producer notify: item {} appended by {}'\ 35 | .format(item, self.name)) 36 | event.set() 37 | event.clear() 38 | 39 | if __name__ == "__main__": 40 | t1 = Producer() 41 | t2 = Consumer() 42 | 43 | t1.start() 44 | t2.start() 45 | 46 | t1.join() 47 | t2.join() 48 | -------------------------------------------------------------------------------- /Chapter02/MyThreadClass.py: -------------------------------------------------------------------------------- 1 | import time 2 | import os 3 | from random import randint 4 | from threading import Thread 5 | 6 | class MyThreadClass (Thread): 7 | def __init__(self, name, duration): 8 | Thread.__init__(self) 9 | self.name = name 10 | self.duration = duration 11 | def run(self): 12 | print ("---> " + self.name + \ 13 | " running, belonging to process ID "\ 14 | + str(os.getpid()) + "\n") 15 | time.sleep(self.duration) 16 | print ("---> " + self.name + " over\n") 17 | 18 | 19 | def main(): 20 | start_time = time.time() 21 | 22 | # Thread Creation 23 | thread1 = MyThreadClass("Thread#1 ", randint(1,10)) 24 | thread2 = MyThreadClass("Thread#2 ", randint(1,10)) 25 | thread3 = MyThreadClass("Thread#3 ", randint(1,10)) 26 | thread4 = MyThreadClass("Thread#4 ", randint(1,10)) 27 | thread5 = MyThreadClass("Thread#5 ", randint(1,10)) 28 | thread6 = MyThreadClass("Thread#6 ", randint(1,10)) 29 | thread7 = MyThreadClass("Thread#7 ", randint(1,10)) 30 | thread8 = MyThreadClass("Thread#8 ", randint(1,10)) 31 | thread9 = MyThreadClass("Thread#9 ", randint(1,10)) 32 | 33 | # Thread Running 34 | thread1.start() 35 | thread2.start() 36 | thread3.start() 37 | thread4.start() 38 | thread5.start() 39 | thread6.start() 40 | thread7.start() 41 | thread8.start() 42 | thread9.start() 43 | 44 | # Thread joining 45 | thread1.join() 46 | thread2.join() 47 | thread3.join() 48 | thread4.join() 49 | thread5.join() 50 | thread6.join() 51 | thread7.join() 52 | thread8.join() 53 | thread9.join() 54 | 55 | # End 56 | print("End") 57 | 58 | #Execution Time 59 | print("--- %s seconds ---" % (time.time() - start_time)) 60 | 61 | 62 | if __name__ == "__main__": 63 | main() 64 | 65 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /Chapter02/MyThreadClass_lock.py: -------------------------------------------------------------------------------- 1 | import threading 2 | import time 3 | import os 4 | from threading import Thread 5 | from random import randint 6 | 7 | # Lock Definition 8 | threadLock = threading.Lock() 9 | 10 | class MyThreadClass (Thread): 11 | def __init__(self, name, duration): 12 | Thread.__init__(self) 13 | self.name = name 14 | self.duration = duration 15 | def run(self): 16 | #Acquire the Lock 17 | threadLock.acquire() 18 | print ("---> " + self.name + \ 19 | " running, belonging to process ID "\ 20 | + str(os.getpid()) + "\n") 21 | time.sleep(self.duration) 22 | print ("---> " + self.name + " over\n") 23 | #Release the Lock 24 | threadLock.release() 25 | 26 | 27 | def main(): 28 | start_time = time.time() 29 | # Thread Creation 30 | thread1 = MyThreadClass("Thread#1 ", randint(1,10)) 31 | thread2 = MyThreadClass("Thread#2 ", randint(1,10)) 32 | thread3 = MyThreadClass("Thread#3 ", randint(1,10)) 33 | thread4 = MyThreadClass("Thread#4 ", randint(1,10)) 34 | thread5 = MyThreadClass("Thread#5 ", randint(1,10)) 35 | thread6 = MyThreadClass("Thread#6 ", randint(1,10)) 36 | thread7 = MyThreadClass("Thread#7 ", randint(1,10)) 37 | thread8 = MyThreadClass("Thread#8 ", randint(1,10)) 38 | thread9 = MyThreadClass("Thread#9 ", randint(1,10)) 39 | 40 | # Thread Running 41 | thread1.start() 42 | thread2.start() 43 | thread3.start() 44 | thread4.start() 45 | thread5.start() 46 | thread6.start() 47 | thread7.start() 48 | thread8.start() 49 | thread9.start() 50 | 51 | # Thread joining 52 | thread1.join() 53 | thread2.join() 54 | thread3.join() 55 | thread4.join() 56 | thread5.join() 57 | thread6.join() 58 | thread7.join() 59 | thread8.join() 60 | thread9.join() 61 | 62 | # End 63 | print("End") 64 | 65 | #Execution Time 66 | print("--- %s seconds ---" % (time.time() - start_time)) 67 | 68 | 69 | if __name__ == "__main__": 70 | main() 71 | 72 | 73 | 74 | 75 | -------------------------------------------------------------------------------- /Chapter02/MyThreadClass_lock_2.py: -------------------------------------------------------------------------------- 1 | import threading 2 | import time 3 | import os 4 | from threading import Thread 5 | from random import randint 6 | 7 | # Lock Definition 8 | threadLock = threading.Lock() 9 | 10 | class MyThreadClass (Thread): 11 | def __init__(self, name, duration): 12 | Thread.__init__(self) 13 | self.name = name 14 | self.duration = duration 15 | def run(self): 16 | #Acquire the Lock 17 | threadLock.acquire() 18 | print ("---> " + self.name + \ 19 | " running, belonging to process ID "\ 20 | + str(os.getpid()) + "\n") 21 | threadLock.release() 22 | time.sleep(self.duration) 23 | print ("---> " + self.name + " over\n") 24 | #Release the Lock 25 | 26 | 27 | def main(): 28 | start_time = time.time() 29 | 30 | # Thread Creation 31 | thread1 = MyThreadClass("Thread#1 ", randint(1,10)) 32 | thread2 = MyThreadClass("Thread#2 ", randint(1,10)) 33 | thread3 = MyThreadClass("Thread#3 ", randint(1,10)) 34 | thread4 = MyThreadClass("Thread#4 ", randint(1,10)) 35 | thread5 = MyThreadClass("Thread#5 ", randint(1,10)) 36 | thread6 = MyThreadClass("Thread#6 ", randint(1,10)) 37 | thread7 = MyThreadClass("Thread#7 ", randint(1,10)) 38 | thread8 = MyThreadClass("Thread#8 ", randint(1,10)) 39 | thread9 = MyThreadClass("Thread#9 ", randint(1,10)) 40 | 41 | # Thread Running 42 | thread1.start() 43 | thread2.start() 44 | thread3.start() 45 | thread4.start() 46 | thread5.start() 47 | thread6.start() 48 | thread7.start() 49 | thread8.start() 50 | thread9.start() 51 | 52 | # Thread joining 53 | thread1.join() 54 | thread2.join() 55 | thread3.join() 56 | thread4.join() 57 | thread5.join() 58 | thread6.join() 59 | thread7.join() 60 | thread8.join() 61 | thread9.join() 62 | 63 | # End 64 | print("End") 65 | 66 | #Execution Time 67 | print("--- %s seconds ---" % (time.time() - start_time)) 68 | 69 | 70 | if __name__ == "__main__": 71 | main() 72 | 73 | 74 | 75 | 76 | -------------------------------------------------------------------------------- /Chapter02/Rlock.py: -------------------------------------------------------------------------------- 1 | import threading 2 | import time 3 | import random 4 | 5 | 6 | class Box: 7 | def __init__(self): 8 | self.lock = threading.RLock() 9 | self.total_items = 0 10 | 11 | def execute(self, value): 12 | with self.lock: 13 | self.total_items += value 14 | 15 | def add(self): 16 | with self.lock: 17 | self.execute(1) 18 | 19 | def remove(self): 20 | with self.lock: 21 | self.execute(-1) 22 | 23 | def adder(box, items): 24 | print("N° {} items to ADD \n".format(items)) 25 | while items: 26 | box.add() 27 | time.sleep(1) 28 | items -= 1 29 | print("ADDED one item -->{} item to ADD \n".format(items)) 30 | 31 | 32 | 33 | def remover(box, items): 34 | print("N° {} items to REMOVE \n".format(items)) 35 | while items: 36 | box.remove() 37 | time.sleep(1) 38 | items -= 1 39 | print("REMOVED one item -->{} item to REMOVE \n".format(items)) 40 | 41 | 42 | def main(): 43 | items = 10 44 | box = Box() 45 | 46 | t1 = threading.Thread(target=adder, \ 47 | args=(box, random.randint(10,20))) 48 | t2 = threading.Thread(target=remover, \ 49 | args=(box, random.randint(1,10))) 50 | 51 | t1.start() 52 | t2.start() 53 | 54 | 55 | t1.join() 56 | t2.join() 57 | 58 | 59 | if __name__ == "__main__": 60 | main() 61 | -------------------------------------------------------------------------------- /Chapter02/Semaphore.py: -------------------------------------------------------------------------------- 1 | import logging 2 | import threading 3 | import time 4 | import random 5 | 6 | LOG_FORMAT = '%(asctime)s %(threadName)-17s %(levelname)-8s %(message)s' 7 | logging.basicConfig(level=logging.INFO, format=LOG_FORMAT) 8 | 9 | 10 | semaphore = threading.Semaphore(0) 11 | item = 0 12 | 13 | 14 | def consumer(): 15 | logging.info('Consumer is waiting') 16 | semaphore.acquire() 17 | logging.info('Consumer notify: item number {}'.format(item)) 18 | 19 | 20 | def producer(): 21 | global item 22 | time.sleep(3) 23 | item = random.randint(0, 1000) 24 | logging.info('Producer notify: item number {}'.format(item)) 25 | semaphore.release() 26 | 27 | 28 | def main(): 29 | for i in range(10): 30 | t1 = threading.Thread(target=consumer) 31 | t2 = threading.Thread(target=producer) 32 | 33 | t1.start() 34 | t2.start() 35 | 36 | t1.join() 37 | t2.join() 38 | 39 | 40 | if __name__ == "__main__": 41 | main() 42 | -------------------------------------------------------------------------------- /Chapter02/Thread_definition.py: -------------------------------------------------------------------------------- 1 | import threading 2 | 3 | 4 | def my_func(thread_number): 5 | return print('my_func called by thread N°{}'.format(thread_number)) 6 | 7 | 8 | def main(): 9 | threads = [] 10 | for i in range(10): 11 | t = threading.Thread(target=my_func, args=(i,)) 12 | threads.append(t) 13 | t.start() 14 | t.join() 15 | 16 | if __name__ == "__main__": 17 | main() 18 | -------------------------------------------------------------------------------- /Chapter02/Thread_determine.py: -------------------------------------------------------------------------------- 1 | import threading 2 | import time 3 | 4 | def function_A(): 5 | print (threading.currentThread().getName()+str('--> starting \n')) 6 | time.sleep(2) 7 | print (threading.currentThread().getName()+str( '--> exiting \n')) 8 | return 9 | 10 | def function_B(): 11 | print (threading.currentThread().getName()+str('--> starting \n')) 12 | time.sleep(2) 13 | print (threading.currentThread().getName()+str( '--> exiting \n')) 14 | return 15 | 16 | def function_C(): 17 | print (threading.currentThread().getName()+str('--> starting \n')) 18 | time.sleep(2) 19 | print (threading.currentThread().getName()+str( '--> exiting \n')) 20 | return 21 | 22 | 23 | if __name__ == "__main__": 24 | 25 | t1 = threading.Thread(name='function_A', target=function_A) 26 | t2 = threading.Thread(name='function_B', target=function_B) 27 | t3 = threading.Thread(name='function_C',target=function_C) 28 | 29 | t1.start() 30 | t2.start() 31 | t3.start() 32 | 33 | t1.join() 34 | t2.join() 35 | t3.join() 36 | -------------------------------------------------------------------------------- /Chapter02/Thread_name_and_processes.py: -------------------------------------------------------------------------------- 1 | from threading import Thread 2 | import time 3 | import os 4 | 5 | class MyThreadClass (Thread): 6 | def __init__(self, name): 7 | Thread.__init__(self) 8 | self.name = name 9 | 10 | def run(self): 11 | print("ID of process running {}".format(self.name)) #, " is {} \n".format(os.getpid())) 12 | 13 | def main(): 14 | from random import randint 15 | # Thread Creation 16 | thread1 = MyThreadClass("Thread#1 ") 17 | thread2 = MyThreadClass("Thread#2 ") 18 | 19 | # Thread Running 20 | thread1.start() 21 | thread2.start() 22 | 23 | 24 | # Thread joining 25 | thread1.join() 26 | thread2.join() 27 | 28 | # End 29 | print("End") 30 | 31 | 32 | if __name__ == "__main__": 33 | main() 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /Chapter02/Threading_with_queue.py: -------------------------------------------------------------------------------- 1 | """"Thread synchronisation with queue""" 2 | 3 | from threading import Thread 4 | from queue import Queue 5 | import time 6 | import random 7 | 8 | 9 | class Producer(Thread): 10 | 11 | def __init__(self, queue): 12 | Thread.__init__(self) 13 | self.queue = queue 14 | 15 | def run(self): 16 | for i in range(5): 17 | item = random.randint(0, 256) 18 | self.queue.put(item) 19 | print('Producer notify : item N°%d appended to queue by %s\n'\ 20 | % (item, self.name)) 21 | time.sleep(1) 22 | 23 | 24 | class Consumer(Thread): 25 | 26 | def __init__(self, queue): 27 | Thread.__init__(self) 28 | self.queue = queue 29 | 30 | def run(self): 31 | while True: 32 | item = self.queue.get() 33 | print('Consumer notify : %d popped from queue by %s'\ 34 | % (item, self.name)) 35 | self.queue.task_done() 36 | 37 | if __name__ == '__main__': 38 | queue = Queue() 39 | 40 | t1 = Producer(queue) 41 | t2 = Consumer(queue) 42 | t3 = Consumer(queue) 43 | t4 = Consumer(queue) 44 | 45 | t1.start() 46 | t2.start() 47 | t3.start() 48 | t4.start() 49 | 50 | t1.join() 51 | t2.join() 52 | t3.join() 53 | t4.join() 54 | -------------------------------------------------------------------------------- /Chapter03/__pycache__/myFunc.cpython-35.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Python-Parallel-Programming-Cookbook-Second-Edition/a10f0b2ba69995a6a8697e68ae0b53a20f4c04c7/Chapter03/__pycache__/myFunc.cpython-35.pyc -------------------------------------------------------------------------------- /Chapter03/communicating_with_pipe.py: -------------------------------------------------------------------------------- 1 | ##Using Pipes with multiprocessing – Chapter 3: Process Based Parallelism 2 | 3 | import multiprocessing 4 | 5 | 6 | def create_items(pipe): 7 | output_pipe, _ = pipe 8 | for item in range(10): 9 | output_pipe.send(item) 10 | output_pipe.close() 11 | 12 | def multiply_items(pipe_1, pipe_2): 13 | close, input_pipe = pipe_1 14 | close.close() 15 | output_pipe, _ = pipe_2 16 | try: 17 | while True: 18 | item = input_pipe.recv() 19 | output_pipe.send(item * item) 20 | except EOFError: 21 | output_pipe.close() 22 | 23 | 24 | if __name__== '__main__': 25 | 26 | #First process pipe with numbers from 0 to 9 27 | pipe_1 = multiprocessing.Pipe(True) 28 | process_pipe_1 = \ 29 | multiprocessing.Process\ 30 | (target=create_items, args=(pipe_1,)) 31 | process_pipe_1.start() 32 | 33 | #second pipe, 34 | pipe_2 = multiprocessing.Pipe(True) 35 | process_pipe_2 = \ 36 | multiprocessing.Process\ 37 | (target=multiply_items, args=(pipe_1, pipe_2,)) 38 | process_pipe_2.start() 39 | 40 | pipe_1[0].close() 41 | pipe_2[0].close() 42 | 43 | try: 44 | while True: 45 | 46 | print (pipe_2[1].recv()) 47 | except EOFError: 48 | print ("End") 49 | -------------------------------------------------------------------------------- /Chapter03/communicating_with_queue.py: -------------------------------------------------------------------------------- 1 | import multiprocessing 2 | import random 3 | import time 4 | 5 | class producer(multiprocessing.Process): 6 | def __init__(self, queue): 7 | multiprocessing.Process.__init__(self) 8 | self.queue = queue 9 | 10 | def run(self) : 11 | for i in range(10): 12 | item = random.randint(0, 256) 13 | self.queue.put(item) 14 | print ("Process Producer : item %d appended to queue %s"\ 15 | % (item,self.name)) 16 | time.sleep(1) 17 | print ("The size of queue is %s"\ 18 | % self.queue.qsize()) 19 | 20 | class consumer(multiprocessing.Process): 21 | def __init__(self, queue): 22 | multiprocessing.Process.__init__(self) 23 | self.queue = queue 24 | 25 | def run(self): 26 | while True: 27 | if (self.queue.empty()): 28 | print("the queue is empty") 29 | break 30 | else : 31 | time.sleep(2) 32 | item = self.queue.get() 33 | print ('Process Consumer : item %d popped \ 34 | from by %s \n'\ 35 | % (item, self.name)) 36 | time.sleep(1) 37 | 38 | 39 | if __name__ == '__main__': 40 | queue = multiprocessing.Queue() 41 | process_producer = producer(queue) 42 | process_consumer = consumer(queue) 43 | process_producer.start() 44 | process_consumer.start() 45 | process_producer.join() 46 | process_consumer.join() 47 | 48 | 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /Chapter03/killing_processes.py: -------------------------------------------------------------------------------- 1 | import multiprocessing 2 | import time 3 | 4 | def foo(): 5 | print ('Starting function') 6 | for i in range(0,10): 7 | print('-->%d\n' %i) 8 | time.sleep(1) 9 | print ('Finished function') 10 | 11 | if __name__ == '__main__': 12 | p = multiprocessing.Process(target=foo) 13 | print ('Process before execution:', p, p.is_alive()) 14 | p.start() 15 | print ('Process running:', p, p.is_alive()) 16 | p.terminate() 17 | print ('Process terminated:', p, p.is_alive()) 18 | p.join() 19 | print ('Process joined:', p, p.is_alive()) 20 | print ('Process exit code:', p.exitcode) 21 | -------------------------------------------------------------------------------- /Chapter03/myFunc.py: -------------------------------------------------------------------------------- 1 | def myFunc(i): 2 | print ('calling myFunc from process n°: %s' %i) 3 | for j in range (0,i): 4 | print('output from myFunc is :%s' %j) 5 | return 6 | -------------------------------------------------------------------------------- /Chapter03/naming_processes.py: -------------------------------------------------------------------------------- 1 | import multiprocessing 2 | import time 3 | 4 | def myFunc(): 5 | name = multiprocessing.current_process().name 6 | print ("Starting process name = %s \n" %name) 7 | time.sleep(3) 8 | print ("Exiting process name = %s \n" %name) 9 | 10 | if __name__ == '__main__': 11 | process_with_name = multiprocessing.Process\ 12 | (name='myFunc process',\ 13 | target=myFunc) 14 | 15 | #process_with_name.daemon = True 16 | 17 | process_with_default_name = multiprocessing.Process\ 18 | (target=myFunc) 19 | 20 | process_with_name.start() 21 | process_with_default_name.start() 22 | 23 | process_with_name.join() 24 | process_with_default_name.join() 25 | 26 | -------------------------------------------------------------------------------- /Chapter03/process_in_subclass.py: -------------------------------------------------------------------------------- 1 | import multiprocessing 2 | 3 | class MyProcess(multiprocessing.Process): 4 | 5 | def run(self): 6 | print ('called run method in %s' %self.name) 7 | return 8 | 9 | if __name__ == '__main__': 10 | for i in range(10): 11 | process = MyProcess() 12 | process.start() 13 | process.join() 14 | 15 | -------------------------------------------------------------------------------- /Chapter03/process_pool.py: -------------------------------------------------------------------------------- 1 | #Using a Process Pool – Chapter 3: Process Based Parallelism 2 | import multiprocessing 3 | 4 | def function_square(data): 5 | result = data*data 6 | return result 7 | 8 | 9 | if __name__ == '__main__': 10 | inputs = list(range(0,100)) 11 | pool = multiprocessing.Pool(processes=4) 12 | pool_outputs = pool.map(function_square, inputs) 13 | 14 | pool.close() 15 | pool.join() 16 | print ('Pool :', pool_outputs) 17 | -------------------------------------------------------------------------------- /Chapter03/processes_barrier.py: -------------------------------------------------------------------------------- 1 | import multiprocessing 2 | from multiprocessing import Barrier, Lock, Process 3 | from time import time 4 | from datetime import datetime 5 | 6 | 7 | def test_with_barrier(synchronizer, serializer): 8 | name = multiprocessing.current_process().name 9 | synchronizer.wait() 10 | now = time() 11 | with serializer: 12 | print("process %s ----> %s" \ 13 | %(name,datetime.fromtimestamp(now))) 14 | 15 | def test_without_barrier(): 16 | name = multiprocessing.current_process().name 17 | now = time() 18 | print("process %s ----> %s" \ 19 | %(name ,datetime.fromtimestamp(now))) 20 | 21 | if __name__ == '__main__': 22 | synchronizer = Barrier(2) 23 | serializer = Lock() 24 | Process(name='p1 - test_with_barrier'\ 25 | ,target=test_with_barrier,\ 26 | args=(synchronizer,serializer)).start() 27 | Process(name='p2 - test_with_barrier'\ 28 | ,target=test_with_barrier,\ 29 | args=(synchronizer,serializer)).start() 30 | Process(name='p3 - test_without_barrier'\ 31 | ,target=test_without_barrier).start() 32 | Process(name='p4 - test_without_barrier'\ 33 | ,target=test_without_barrier).start() 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /Chapter03/run_background_processes.py: -------------------------------------------------------------------------------- 1 | import multiprocessing 2 | import time 3 | 4 | def foo(): 5 | name = multiprocessing.current_process().name 6 | print ("Starting %s \n" %name) 7 | if name == 'background_process': 8 | for i in range(0,5): 9 | print('---> %d \n' %i) 10 | time.sleep(1) 11 | else: 12 | for i in range(5,10): 13 | print('---> %d \n' %i) 14 | time.sleep(1) 15 | print ("Exiting %s \n" %name) 16 | 17 | 18 | if __name__ == '__main__': 19 | background_process = multiprocessing.Process\ 20 | (name='background_process',\ 21 | target=foo) 22 | background_process.daemon = True 23 | 24 | NO_background_process = multiprocessing.Process\ 25 | (name='NO_background_process',\ 26 | target=foo) 27 | 28 | NO_background_process.daemon = False 29 | 30 | background_process.start() 31 | NO_background_process.start() 32 | 33 | 34 | -------------------------------------------------------------------------------- /Chapter03/run_background_processes_no_daemons.py: -------------------------------------------------------------------------------- 1 | import multiprocessing 2 | import time 3 | 4 | def foo(): 5 | name = multiprocessing.current_process().name 6 | print ("Starting %s \n" %name) 7 | if name == 'background_process': 8 | for i in range(0,5): 9 | print('---> %d \n' %i) 10 | time.sleep(1) 11 | else: 12 | for i in range(5,10): 13 | print('---> %d \n' %i) 14 | time.sleep(1) 15 | print ("Exiting %s \n" %name) 16 | 17 | 18 | if __name__ == '__main__': 19 | background_process = multiprocessing.Process\ 20 | (name='background_process',\ 21 | target=foo) 22 | background_process.daemon = False 23 | 24 | NO_background_process = multiprocessing.Process\ 25 | (name='NO_background_process',\ 26 | target=foo) 27 | 28 | NO_background_process.daemon = False 29 | 30 | background_process.start() 31 | NO_background_process.start() 32 | 33 | 34 | -------------------------------------------------------------------------------- /Chapter03/spawning_processes.py: -------------------------------------------------------------------------------- 1 | #Spawn a Process – Chapter 3: Process Based Parallelism 2 | import multiprocessing 3 | 4 | def myFunc(i): 5 | print ('calling myFunc from process n°: %s' %i) 6 | for j in range (0,i): 7 | print('output from myFunc is :%s' %j) 8 | return 9 | 10 | if __name__ == '__main__': 11 | for i in range(6): 12 | process = multiprocessing.Process(target=myFunc, args=(i,)) 13 | process.start() 14 | process.join() 15 | 16 | -------------------------------------------------------------------------------- /Chapter03/spawning_processes_namespace.py: -------------------------------------------------------------------------------- 1 | import multiprocessing 2 | from myFunc import myFunc 3 | 4 | if __name__ == '__main__': 5 | for i in range(6): 6 | process = multiprocessing.Process(target=myFunc, args=(i,)) 7 | process.start() 8 | process.join() 9 | 10 | -------------------------------------------------------------------------------- /Chapter04/alltoall.py: -------------------------------------------------------------------------------- 1 | from mpi4py import MPI 2 | import numpy 3 | 4 | comm = MPI.COMM_WORLD 5 | size = comm.Get_size() 6 | rank = comm.Get_rank() 7 | 8 | 9 | senddata = (rank+1)*numpy.arange(size,dtype=int) 10 | recvdata = numpy.empty(size,dtype=int) 11 | comm.Alltoall(senddata,recvdata) 12 | 13 | 14 | print(" process %s sending %s receiving %s"\ 15 | %(rank , senddata , recvdata)) 16 | -------------------------------------------------------------------------------- /Chapter04/broadcast.py: -------------------------------------------------------------------------------- 1 | from mpi4py import MPI 2 | 3 | comm = MPI.COMM_WORLD 4 | rank = comm.Get_rank() 5 | 6 | if rank == 0: 7 | variable_to_share = 100 8 | 9 | else: 10 | variable_to_share = None 11 | 12 | variable_to_share = comm.bcast(variable_to_share, root=0) 13 | print("process = %d" %rank + " variable shared = %d " %variable_to_share) 14 | -------------------------------------------------------------------------------- /Chapter04/deadLockProblems.py: -------------------------------------------------------------------------------- 1 | from mpi4py import MPI 2 | 3 | comm=MPI.COMM_WORLD 4 | rank = comm.rank 5 | print("my rank is %i" % (rank)) 6 | 7 | if rank==1: 8 | data_send= "a" 9 | destination_process = 5 10 | source_process = 5 11 | 12 | data_received=comm.recv(source=source_process) 13 | comm.send(data_send,dest=destination_process) 14 | 15 | print ("sending data %s " %data_send + \ 16 | "to process %d" %destination_process) 17 | print ("data received is = %s" %data_received) 18 | 19 | 20 | 21 | if rank==5: 22 | data_send= "b" 23 | destination_process = 1 24 | source_process = 1 25 | 26 | comm.send(data_send,dest=destination_process) 27 | data_received=comm.recv(source=source_process) 28 | 29 | 30 | print ("sending data %s :" %data_send + \ 31 | "to process %d" %destination_process) 32 | print ("data received is = %s" %data_received) 33 | 34 | -------------------------------------------------------------------------------- /Chapter04/gather.py: -------------------------------------------------------------------------------- 1 | from mpi4py import MPI 2 | 3 | comm = MPI.COMM_WORLD 4 | size = comm.Get_size() 5 | rank = comm.Get_rank() 6 | data = (rank+1)**2 7 | 8 | data = comm.gather(data, root=0) 9 | if rank == 0: 10 | print ("rank = %s " %rank +\ 11 | "...receiving data to other process") 12 | for i in range(1,size): 13 | 14 | value = data[i] 15 | print(" process %s receiving %s from process %s"\ 16 | %(rank , value , i)) 17 | 18 | -------------------------------------------------------------------------------- /Chapter04/helloworld_MPI.py: -------------------------------------------------------------------------------- 1 | #hello.py 2 | from mpi4py import MPI 3 | comm = MPI.COMM_WORLD 4 | rank = comm.Get_rank() 5 | print ("hello world from process ", rank) 6 | -------------------------------------------------------------------------------- /Chapter04/pointToPointCommunication.py: -------------------------------------------------------------------------------- 1 | from mpi4py import MPI 2 | 3 | comm=MPI.COMM_WORLD 4 | rank = comm.rank 5 | print("my rank is : " , rank) 6 | 7 | if rank==0: 8 | data= 10000000 9 | destination_process = 4 10 | comm.send(data,dest=destination_process) 11 | print ("sending data %s " %data +\ 12 | "to process %d" %destination_process) 13 | 14 | if rank==1: 15 | destination_process = 8 16 | data= "hello" 17 | comm.send(data,dest=destination_process) 18 | print ("sending data %s :" %data + \ 19 | "to process %d" %destination_process) 20 | 21 | 22 | if rank==4: 23 | data=comm.recv(source=0) 24 | print ("data received is = %s" %data) 25 | 26 | 27 | if rank==8: 28 | data1=comm.recv(source=1) 29 | print ("data1 received is = %s" %data1) 30 | -------------------------------------------------------------------------------- /Chapter04/reduction.py: -------------------------------------------------------------------------------- 1 | import numpy 2 | from mpi4py import MPI 3 | comm = MPI.COMM_WORLD 4 | size = comm.size 5 | rank = comm.rank 6 | 7 | 8 | array_size = 10 9 | recvdata = numpy.zeros(array_size,dtype=numpy.int) 10 | senddata = (rank+1)*numpy.arange(array_size,dtype=numpy.int) 11 | 12 | print(" process %s sending %s " %(rank , senddata)) 13 | 14 | 15 | comm.Reduce(senddata,recvdata,root=0,op=MPI.SUM) 16 | print ('on task',rank,'after Reduce: data = ',recvdata) 17 | 18 | 19 | -------------------------------------------------------------------------------- /Chapter04/scatter.py: -------------------------------------------------------------------------------- 1 | from mpi4py import MPI 2 | 3 | comm = MPI.COMM_WORLD 4 | rank = comm.Get_rank() 5 | 6 | if rank == 0: 7 | array_to_share = [1, 2, 3, 4 ,5 ,6 ,7, 8 ,9 ,10] 8 | 9 | else: 10 | array_to_share = None 11 | 12 | recvbuf = comm.scatter(array_to_share, root=0) 13 | print("process = %d" % rank + " variable shared = %d " % recvbuf ) 14 | -------------------------------------------------------------------------------- /Chapter04/virtualTopology.py: -------------------------------------------------------------------------------- 1 | from mpi4py import MPI 2 | import numpy as np 3 | 4 | UP = 0 5 | DOWN = 1 6 | LEFT = 2 7 | RIGHT = 3 8 | neighbour_processes = [0,0,0,0] 9 | if __name__ == "__main__": 10 | comm = MPI.COMM_WORLD 11 | rank = comm.rank 12 | size = comm.size 13 | 14 | grid_row = int(np.floor(np.sqrt(comm.size))) 15 | grid_column = comm.size // grid_row 16 | 17 | 18 | if grid_row*grid_column > size: 19 | grid_column -= 1 20 | if grid_row*grid_column > size: 21 | grid_row -= 1 22 | 23 | if (rank == 0) : 24 | print("Building a %d x %d grid topology:"\ 25 | % (grid_row, grid_column) ) 26 | 27 | 28 | cartesian_communicator = \ 29 | comm.Create_cart( \ 30 | (grid_row, grid_column), \ 31 | periods=(True, True), reorder=True) 32 | my_mpi_row, my_mpi_col = \ 33 | cartesian_communicator.Get_coords\ 34 | ( cartesian_communicator.rank ) 35 | 36 | 37 | neighbour_processes[UP], neighbour_processes[DOWN]\ 38 | = cartesian_communicator.Shift(0, 1) 39 | neighbour_processes[LEFT], \ 40 | neighbour_processes[RIGHT] = \ 41 | cartesian_communicator.Shift(1, 1) 42 | print ("Process = %s \ 43 | row = %s \ 44 | column = %s \n----> \nneighbour_processes[UP] = %s\n\ 45 | neighbour_processes[DOWN] = %s\n\ 46 | neighbour_processes[LEFT] =%s\nneighbour_processes[RIGHT]=%s\n" \ 47 | %(rank, my_mpi_row, \ 48 | my_mpi_col,neighbour_processes[UP], \ 49 | neighbour_processes[DOWN], \ 50 | neighbour_processes[LEFT] , \ 51 | neighbour_processes[RIGHT])) 52 | 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /Chapter05/asyncio_and_futures.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | import sys 3 | 4 | 5 | @asyncio.coroutine 6 | def first_coroutine(future, num): 7 | count = 0 8 | for i in range(1, num + 1): 9 | count += 1 10 | yield from asyncio.sleep(4) 11 | future.set_result('First coroutine (sum of N ints) result = %s' % count) 12 | 13 | 14 | @asyncio.coroutine 15 | def second_coroutine(future, num): 16 | count = 1 17 | for i in range(2, num + 1): 18 | count *= i 19 | yield from asyncio.sleep(4) 20 | future.set_result('Second coroutine (factorial) result = %s' % count) 21 | 22 | 23 | def got_result(future): 24 | print(future.result()) 25 | 26 | if __name__ == '__main__': 27 | num1 = int(sys.argv[1]) 28 | num2 = int(sys.argv[2]) 29 | 30 | loop = asyncio.get_event_loop() 31 | future1 = asyncio.Future() 32 | future2 = asyncio.Future() 33 | 34 | tasks = [first_coroutine(future1, num1), 35 | second_coroutine(future2, num2)] 36 | 37 | future1.add_done_callback(got_result) 38 | future2.add_done_callback(got_result) 39 | 40 | loop.run_until_complete(asyncio.wait(tasks)) 41 | loop.close() 42 | -------------------------------------------------------------------------------- /Chapter05/asyncio_coroutine.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | import time 3 | from random import randint 4 | 5 | 6 | @asyncio.coroutine 7 | def start_state(): 8 | print('Start State called\n') 9 | input_value = randint(0, 1) 10 | time.sleep(1) 11 | 12 | if input_value == 0: 13 | result = yield from state2(input_value) 14 | else: 15 | result = yield from state1(input_value) 16 | 17 | print('Resume of the Transition : \nStart State calling ' + result) 18 | 19 | 20 | @asyncio.coroutine 21 | def state1(transition_value): 22 | output_value = 'State 1 with transition value = %s\n' % transition_value 23 | input_value = randint(0, 1) 24 | time.sleep(1) 25 | 26 | print('...evaluating...') 27 | if input_value == 0: 28 | result = yield from state3(input_value) 29 | else: 30 | result = yield from state2(input_value) 31 | 32 | return output_value + 'State 1 calling %s' % result 33 | 34 | 35 | @asyncio.coroutine 36 | def state2(transition_value): 37 | output_value = 'State 2 with transition value = %s\n' % transition_value 38 | input_value = randint(0, 1) 39 | time.sleep(1) 40 | 41 | print('...evaluating...') 42 | if input_value == 0: 43 | result = yield from state1(input_value) 44 | else: 45 | result = yield from state3(input_value) 46 | 47 | return output_value + 'State 2 calling %s' % result 48 | 49 | 50 | @asyncio.coroutine 51 | def state3(transition_value): 52 | output_value = 'State 3 with transition value = %s\n' % transition_value 53 | input_value = randint(0, 1) 54 | time.sleep(1) 55 | 56 | print('...evaluating...') 57 | if input_value == 0: 58 | result = yield from state1(input_value) 59 | else: 60 | result = yield from end_state(input_value) 61 | 62 | return output_value + 'State 3 calling %s' % result 63 | 64 | 65 | @asyncio.coroutine 66 | def end_state(transition_value): 67 | output_value = 'End State with transition value = %s\n' % transition_value 68 | print('...stop computation...') 69 | return output_value 70 | 71 | 72 | if __name__ == '__main__': 73 | print('Finite State Machine simulation with Asyncio Coroutine') 74 | loop = asyncio.get_event_loop() 75 | loop.run_until_complete(start_state()) 76 | -------------------------------------------------------------------------------- /Chapter05/asyncio_event_loop.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | import time 3 | import random 4 | 5 | def task_A(end_time, loop): 6 | print ("task_A called") 7 | time.sleep(random.randint(0, 5)) 8 | if (loop.time() + 1.0) < end_time: 9 | loop.call_later(1, task_B, end_time, loop) 10 | else: 11 | loop.stop() 12 | 13 | def task_B(end_time, loop): 14 | print ("task_B called ") 15 | time.sleep(random.randint(0, 5)) 16 | if (loop.time() + 1.0) < end_time: 17 | loop.call_later(1, task_C, end_time, loop) 18 | else: 19 | loop.stop() 20 | 21 | def task_C(end_time, loop): 22 | print ("task_C called") 23 | time.sleep(random.randint(0, 5)) 24 | if (loop.time() + 1.0) < end_time: 25 | loop.call_later(1, task_A, end_time, loop) 26 | else: 27 | loop.stop() 28 | 29 | 30 | loop = asyncio.get_event_loop() 31 | end_loop = loop.time() + 60 32 | loop.call_soon(task_A, end_loop, loop) 33 | loop.run_forever() 34 | loop.close() 35 | 36 | -------------------------------------------------------------------------------- /Chapter05/asyncio_task_manipulation.py: -------------------------------------------------------------------------------- 1 | """Asyncio using Asyncio.Task to execute three math functions in parallel""" 2 | 3 | import asyncio 4 | 5 | 6 | @asyncio.coroutine 7 | def factorial(number): 8 | fact = 1 9 | for i in range(2, number + 1): 10 | print('Asyncio.Task: Compute factorial(%s)' % i) 11 | yield from asyncio.sleep(1) 12 | fact *= i 13 | print('Asyncio.Task - factorial(%s) = %s' % (number, fact)) 14 | 15 | 16 | @asyncio.coroutine 17 | def fibonacci(number): 18 | a, b = 0, 1 19 | for i in range(number): 20 | print('Asyncio.Task: Compute fibonacci(%s)' % i) 21 | yield from asyncio.sleep(1) 22 | a, b = b, a + b 23 | print('Asyncio.Task - fibonacci(%s) = %s' % (number, a)) 24 | 25 | 26 | @asyncio.coroutine 27 | def binomial_coefficient(n, k): 28 | result = 1 29 | for i in range(1, k + 1): 30 | result = result*(n - i + 1)/i 31 | print('Asyncio.Task: Compute binomial_coefficient(%s)' % i) 32 | yield from asyncio.sleep(1) 33 | print('Asyncio.Task - binomial_coefficient(%s, %s) = %s' % (n, k, result)) 34 | 35 | 36 | if __name__ == '__main__': 37 | task_list = [asyncio.Task(factorial(10)), 38 | asyncio.Task(fibonacci(10)), 39 | asyncio.Task(binomial_coefficient(20, 10))] 40 | loop = asyncio.get_event_loop() 41 | loop.run_until_complete(asyncio.wait(task_list)) 42 | loop.close() 43 | -------------------------------------------------------------------------------- /Chapter05/concurrent_futures_pooling.py: -------------------------------------------------------------------------------- 1 | import concurrent.futures 2 | import time 3 | 4 | number_list = list(range(1, 11)) 5 | 6 | 7 | def count(number): 8 | for i in range(0,10000000): 9 | i += 1 10 | return i*number 11 | 12 | 13 | def evaluate(item): 14 | result_item = count(item) 15 | print('Item %s, result %s' % (item, result_item)) 16 | 17 | if __name__ == '__main__': 18 | # Sequential Execution 19 | start_time = time.clock() 20 | for item in number_list: 21 | evaluate(item) 22 | print('Sequential Execution in %s seconds' % (time.clock() - start_time)) 23 | 24 | 25 | # Thread Pool Execution 26 | start_time = time.clock() 27 | with concurrent.futures.ThreadPoolExecutor(max_workers=5) as executor: 28 | for item in number_list: 29 | executor.submit(evaluate, item) 30 | print('Thread Pool Execution in %s seconds' % (time.clock() - start_time)) 31 | 32 | 33 | # Process Pool Execution 34 | start_time = time.clock() 35 | with concurrent.futures.ProcessPoolExecutor(max_workers=5) as executor: 36 | for item in number_list: 37 | executor.submit(evaluate, item) 38 | print('Process Pool Execution in %s seconds' % (time.clock() - start_time)) 39 | -------------------------------------------------------------------------------- /Chapter06/Celery/addTask.py: -------------------------------------------------------------------------------- 1 | ### 2 | ## addTask.py :Executing a simple task 3 | ### 4 | 5 | from celery import Celery 6 | 7 | app = Celery('addTask',broker='amqp://guest@localhost//') 8 | 9 | @app.task 10 | def add(x, y): 11 | return x + y 12 | 13 | -------------------------------------------------------------------------------- /Chapter06/Celery/addTask_main.py: -------------------------------------------------------------------------------- 1 | ### 2 | #addTask.py : RUN the AddTask example with 3 | ### 4 | 5 | import addTask 6 | 7 | if __name__ == '__main__': 8 | result = addTask.add.delay(5,5) 9 | 10 | -------------------------------------------------------------------------------- /Chapter06/Pyro4/First Example/pyro_client.py: -------------------------------------------------------------------------------- 1 | import Pyro4 2 | 3 | #uri = input("insert the PYRO4 server URI (help : PYRONAME:server) ").strip() 4 | name = input("What is your name? ").strip() 5 | # use name server object lookup uri shortcut 6 | server = Pyro4.Proxy("PYRONAME:server") 7 | print(server.welcomeMessage(name)) 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /Chapter06/Pyro4/First Example/pyro_server.py: -------------------------------------------------------------------------------- 1 | import Pyro4 2 | 3 | class Server(object): 4 | @Pyro4.expose 5 | def welcomeMessage(self, name): 6 | return ("Hi welcome " + str (name)) 7 | 8 | def startServer(): 9 | server = Server() 10 | # make a Pyro daemon 11 | daemon = Pyro4.Daemon() 12 | # locate the name server running 13 | ns = Pyro4.locateNS() 14 | # register the server as a Pyro object 15 | uri = daemon.register(server) 16 | # register the object with a name in the name server 17 | ns.register("server", uri) 18 | # print the uri so we can use it in the client later 19 | print("Ready. Object uri =", uri) 20 | # start the event loop of the server to wait for calls 21 | daemon.requestLoop() 22 | 23 | if __name__ == "__main__": 24 | startServer() 25 | 26 | -------------------------------------------------------------------------------- /Chapter06/Pyro4/Second Example/__pycache__/chainTopology.cpython-35.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Python-Parallel-Programming-Cookbook-Second-Edition/a10f0b2ba69995a6a8697e68ae0b53a20f4c04c7/Chapter06/Pyro4/Second Example/__pycache__/chainTopology.cpython-35.pyc -------------------------------------------------------------------------------- /Chapter06/Pyro4/Second Example/chainTopology.py: -------------------------------------------------------------------------------- 1 | import Pyro4 2 | 3 | @Pyro4.expose 4 | class Chain(object): 5 | def __init__(self, name, current_server): 6 | self.name = name 7 | self.current_serverName = current_server 8 | self.current_server = None 9 | 10 | def process(self, message): 11 | if self.current_server is None: 12 | self.current_server = Pyro4.core.Proxy("PYRONAME:example.chainTopology." + self.current_serverName) 13 | if self.name in message: 14 | print("Back at %s; the chain is closed!" % self.name) 15 | return ["complete at " + self.name] 16 | else: 17 | print("%s forwarding the message to the object %s" % (self.name, self.current_serverName)) 18 | message.append(self.name) 19 | result = self.current_server.process(message) 20 | result.insert(0, "passed on from " + self.name) 21 | return result 22 | -------------------------------------------------------------------------------- /Chapter06/Pyro4/Second Example/client_chain.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function 2 | import Pyro4 3 | 4 | obj = Pyro4.core.Proxy("PYRONAME:example.chainTopology.1") 5 | print("Result=%s" % obj.process(["hello"])) 6 | -------------------------------------------------------------------------------- /Chapter06/Pyro4/Second Example/desktop.ini: -------------------------------------------------------------------------------- 1 | [LocalizedFileNames] 2 | Command Prompt.lnk=@%SystemRoot%\system32\shell32.dll,-22022 3 | -------------------------------------------------------------------------------- /Chapter06/Pyro4/Second Example/server_chain_1.py: -------------------------------------------------------------------------------- 1 | import Pyro4 2 | import chainTopology 3 | 4 | current_server = "1" 5 | next_server = "2" 6 | 7 | servername = "example.chainTopology." + current_server 8 | 9 | daemon = Pyro4.core.Daemon() 10 | obj = chainTopology.Chain(current_server, next_server) 11 | uri = daemon.register(obj) 12 | ns = Pyro4.locateNS() 13 | ns.register(servername, uri) 14 | 15 | # enter the service loop. 16 | 17 | print("server_%s started " % current_server) 18 | daemon.requestLoop() 19 | -------------------------------------------------------------------------------- /Chapter06/Pyro4/Second Example/server_chain_2.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function 2 | import Pyro4 3 | import chainTopology 4 | 5 | current_server = "2" 6 | next_server = "3" 7 | 8 | servername = "example.chainTopology." + current_server 9 | 10 | daemon = Pyro4.core.Daemon() 11 | obj = chainTopology.Chain(current_server,next_server) 12 | uri = daemon.register(obj) 13 | ns = Pyro4.locateNS() 14 | ns.register(servername, uri) 15 | 16 | # enter the service loop. 17 | print("server_%s started " % current_server) 18 | daemon.requestLoop() 19 | -------------------------------------------------------------------------------- /Chapter06/Pyro4/Second Example/server_chain_3.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function 2 | import Pyro4 3 | import chainTopology 4 | 5 | current_server = "3" 6 | next_server = "1" 7 | 8 | servername = "example.chainTopology." + current_server 9 | 10 | daemon = Pyro4.core.Daemon() 11 | obj = chainTopology.Chain(current_server, next_server) 12 | uri = daemon.register(obj) 13 | ns = Pyro4.locateNS() 14 | ns.register(servername, uri) 15 | 16 | # enter the service loop. 17 | print("server_%s started " % current_server) 18 | daemon.requestLoop() 19 | -------------------------------------------------------------------------------- /Chapter06/socket/addTask.py: -------------------------------------------------------------------------------- 1 | from celery import Celery 2 | 3 | app = Celery('tasks', broker='pyamqp://guest@localhost//') 4 | 5 | @app.task 6 | def add(x, y): 7 | return x + y 8 | -------------------------------------------------------------------------------- /Chapter06/socket/addTask_main.py: -------------------------------------------------------------------------------- 1 | from addTask import add 2 | 3 | 4 | if __name__ == '__main__': 5 | add.delay(5, 5) 6 | 7 | -------------------------------------------------------------------------------- /Chapter06/socket/client.py: -------------------------------------------------------------------------------- 1 | # client .py 2 | import socket 3 | 4 | # create a socket object 5 | s =socket.socket(socket.AF_INET,socket.SOCK_STREAM) 6 | # get local machine name 7 | host=socket.gethostname() 8 | port=9999 9 | # connection to hostname on the port . 10 | s.connect((host,port)) 11 | # Receive no more than 1024 bytes 12 | tm=s.recv(1024) 13 | s.close() 14 | print ("Time connection server:%s"%tm.decode('ascii')) 15 | -------------------------------------------------------------------------------- /Chapter06/socket/client2.py: -------------------------------------------------------------------------------- 1 | import socket 2 | s =socket.socket() 3 | host=socket.gethostname() 4 | port=60000 5 | s.connect((host,port)) 6 | s.send('HelloServer!'.encode()) 7 | with open('received.txt','wb') as f: 8 | print ('file opened') 9 | while True : 10 | print ('receiving data...') 11 | data=s.recv(1024) 12 | if not data: 13 | break 14 | print ('Data=>',data.decode()) 15 | # write data to a file 16 | f.write(data) 17 | f.close() 18 | print ('Successfully get the file') 19 | s.close() 20 | print ('connection closed') 21 | -------------------------------------------------------------------------------- /Chapter06/socket/mytext.txt: -------------------------------------------------------------------------------- 1 | hello!!! -------------------------------------------------------------------------------- /Chapter06/socket/received.txt: -------------------------------------------------------------------------------- 1 | hello!!!->Thankyouforconnecting -------------------------------------------------------------------------------- /Chapter06/socket/server.py: -------------------------------------------------------------------------------- 1 | # server .py 2 | import socket 3 | import time 4 | 5 | # create a socket object 6 | serversocket=socket.socket(socket.AF_INET,socket.SOCK_STREAM) 7 | # get local machine name 8 | host=socket.gethostname() 9 | port=9999 10 | # bind to the port 11 | serversocket.bind((host,port)) 12 | # queue up to 5 requests 13 | serversocket.listen(5) 14 | # establish a connection 15 | while True: 16 | clientsocket,addr=serversocket.accept() 17 | print ("Connected with[addr],[port]%s"%str(addr)) 18 | currentTime=time.ctime(time.time())+"\r\n" 19 | clientsocket.send(currentTime.encode('ascii')) 20 | clientsocket.close() 21 | -------------------------------------------------------------------------------- /Chapter06/socket/server2.py: -------------------------------------------------------------------------------- 1 | # server .py 2 | 3 | import socket 4 | port=60000 5 | s =socket.socket() 6 | host=socket.gethostname() 7 | s.bind((host,port)) 8 | s.listen(15) 9 | print('Server listening....') 10 | while True : 11 | conn,addr=s.accept() 12 | print ('Got connection from',addr) 13 | data=conn.recv(1024) 14 | print ('Server received',repr(data.decode())) 15 | filename='mytext.txt' 16 | f =open(filename,'rb') 17 | l =f.read(1024) 18 | while (l): 19 | conn.send(l) 20 | print ('Sent',repr(l.decode())) 21 | l =f.read(1024) 22 | f.close() 23 | print ('Donesending') 24 | conn.send('->Thank you for connecting'.encode()) 25 | conn.close() 26 | -------------------------------------------------------------------------------- /Chapter07/codes/how to containerize a Python application/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:alpine3.7 2 | COPY . /app 3 | WORKDIR /app 4 | RUN pip install -r requirements.txt 5 | EXPOSE 5000 6 | CMD python ./dockerize.py -------------------------------------------------------------------------------- /Chapter07/codes/how to containerize a Python application/dockerize.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | from flask import Flask 4 | app = Flask(__name__) 5 | @app.route("/") 6 | def hello(): 7 | return "Hello World!" 8 | if __name__ == "__main__": 9 | app.run(host="0.0.0.0", port=int("5000"), debug=True) -------------------------------------------------------------------------------- /Chapter07/codes/how to containerize a Python application/requirements.txt: -------------------------------------------------------------------------------- 1 | flask -------------------------------------------------------------------------------- /Chapter08/Numba/matMulNumba.py: -------------------------------------------------------------------------------- 1 | from numba import guvectorize 2 | import numpy as np 3 | 4 | @guvectorize(['void(int64[:,:], int64[:,:], int64[:,:])'], 5 | '(m,n),(n,p)->(m,p)') 6 | def matmul(A, B, C): 7 | m, n = A.shape 8 | n, p = B.shape 9 | for i in range(m): 10 | for j in range(p): 11 | C[i, j] = 0 12 | for k in range(n): 13 | C[i, j] += A[i, k] * B[k, j] 14 | 15 | dim = 10 16 | A = np.random.randint(dim,size=(dim, dim)) 17 | B = np.random.randint(dim,size=(dim, dim)) 18 | 19 | 20 | C = matmul(A, B) 21 | print("INPUT MATRIX A") 22 | print(":\n%s" % A) 23 | print("INPUT MATRIX B") 24 | print(":\n%s" % B) 25 | print("RESULT MATRIX C = A*B") 26 | print(":\n%s" % C) 27 | -------------------------------------------------------------------------------- /Chapter08/Numba/numba_cuda_detection.py: -------------------------------------------------------------------------------- 1 | import numba.cuda.api 2 | import numba.cuda.cudadrv.libs 3 | 4 | numba.cuda.cudadrv.libs.test() 5 | numba.cuda.api.detect() -------------------------------------------------------------------------------- /Chapter08/Numba/reduceNumba.py: -------------------------------------------------------------------------------- 1 | import numpy 2 | from numba import cuda 3 | 4 | 5 | A = (numpy.arange(10000, dtype=numpy.int64)) + 1 6 | print("vector to reduce = ", A) 7 | 8 | @cuda.reduce 9 | def sum_reduce(a, b): 10 | return a + b 11 | 12 | got = sum_reduce(A) 13 | print("result = " , got) 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /Chapter08/PyCUDA/dealingWithPycuda.py: -------------------------------------------------------------------------------- 1 | import pycuda.driver as drv 2 | drv.init() 3 | print ("%d device(s) found." % drv.Device.count()) 4 | for ordinal in range(drv.Device.count()): 5 | dev = drv.Device(ordinal) 6 | print ("Device #%d: %s" % (ordinal, dev.name())) 7 | print (" Compute Capability: %d.%d" % dev.compute_capability()) 8 | print (" Total Memory: %s KB" % (dev.total_memory()//(1024))) 9 | 10 | -------------------------------------------------------------------------------- /Chapter08/PyCUDA/heterogenousPycuda.py: -------------------------------------------------------------------------------- 1 | import pycuda.driver as cuda 2 | import pycuda.autoinit 3 | from pycuda.compiler import SourceModule 4 | 5 | import numpy 6 | 7 | a = numpy.random.randn(5,5) 8 | a = a.astype(numpy.float32) 9 | 10 | a_gpu = cuda.mem_alloc(a.nbytes) 11 | cuda.memcpy_htod(a_gpu, a) 12 | 13 | mod = SourceModule(""" 14 | __global__ void doubles_matrix(float *a) 15 | { 16 | int idx = threadIdx.x + threadIdx.y*4; 17 | a[idx] *= 2; 18 | } 19 | """) 20 | 21 | func = mod.get_function("doubles_matrix") 22 | func(a_gpu, block=(5,5,1)) 23 | 24 | a_doubled = numpy.empty_like(a) 25 | cuda.memcpy_dtoh(a_doubled, a_gpu) 26 | print ("ORIGINAL MATRIX") 27 | print (a) 28 | print ("DOUBLED MATRIX AFTER PyCUDA EXECUTION") 29 | print (a_doubled) 30 | 31 | -------------------------------------------------------------------------------- /Chapter08/PyCUDA/memManagementPycuda.py: -------------------------------------------------------------------------------- 1 | import pycuda.driver as CUDA 2 | import pycuda.autoinit 3 | from pycuda.compiler import SourceModule 4 | import numpy as np 5 | from pycuda import driver, compiler, gpuarray, tools 6 | 7 | kernel_code_template = """ 8 | __global__ void MatrixMulKernel(float *a, float *b, float *c) 9 | { 10 | int tx = threadIdx.x; 11 | int ty = threadIdx.y; 12 | float Pvalue = 0; 13 | for (int k = 0; k < %(MATRIX_SIZE)s; ++k) { 14 | float Aelement = a[ty * %(MATRIX_SIZE)s + k]; 15 | float Belement = b[k * %(MATRIX_SIZE)s + tx]; 16 | Pvalue += Aelement * Belement; 17 | } 18 | 19 | c[ty * %(MATRIX_SIZE)s + tx] = Pvalue; 20 | } 21 | """ 22 | 23 | MATRIX_SIZE = 5 24 | 25 | a_cpu = np.random.randn(MATRIX_SIZE, MATRIX_SIZE).astype(np.float32) 26 | b_cpu = np.random.randn(MATRIX_SIZE, MATRIX_SIZE).astype(np.float32) 27 | 28 | c_cpu = np.dot(a_cpu, b_cpu) 29 | 30 | a_gpu = gpuarray.to_gpu(a_cpu) 31 | b_gpu = gpuarray.to_gpu(b_cpu) 32 | 33 | c_gpu = gpuarray.empty((MATRIX_SIZE, MATRIX_SIZE), np.float32) 34 | 35 | kernel_code = kernel_code_template % { 36 | 'MATRIX_SIZE': MATRIX_SIZE 37 | } 38 | 39 | mod = compiler.SourceModule(kernel_code) 40 | 41 | matrixmul = mod.get_function("MatrixMulKernel") 42 | 43 | matrixmul( 44 | a_gpu, b_gpu, 45 | c_gpu, 46 | block = (MATRIX_SIZE, MATRIX_SIZE, 1), 47 | ) 48 | 49 | # print the results 50 | print ("-" * 80) 51 | print ("Matrix A (GPU):") 52 | print (a_gpu.get()) 53 | 54 | print ("-" * 80) 55 | print ("Matrix B (GPU):") 56 | print (b_gpu.get()) 57 | 58 | print ("-" * 80) 59 | print ("Matrix C (GPU):") 60 | print (c_gpu.get()) 61 | 62 | print ("-" * 80) 63 | print ("CPU-GPU difference:") 64 | print (c_cpu - c_gpu.get()) 65 | 66 | np.allclose(c_cpu, c_gpu.get()) 67 | 68 | -------------------------------------------------------------------------------- /Chapter08/PyOpenCL/__pycache__/deviceInfoPyopencl.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Python-Parallel-Programming-Cookbook-Second-Edition/a10f0b2ba69995a6a8697e68ae0b53a20f4c04c7/Chapter08/PyOpenCL/__pycache__/deviceInfoPyopencl.cpython-37.pyc -------------------------------------------------------------------------------- /Chapter08/PyOpenCL/deviceInfoPyopencl.py: -------------------------------------------------------------------------------- 1 | import pyopencl as cl 2 | 3 | 4 | def print_device_info() : 5 | print('\n' + '=' * 60 + '\nOpenCL Platforms and Devices') 6 | for platform in cl.get_platforms(): 7 | print('=' * 60) 8 | print('Platform - Name: ' + platform.name) 9 | print('Platform - Vendor: ' + platform.vendor) 10 | print('Platform - Version: ' + platform.version) 11 | print('Platform - Profile: ' + platform.profile) 12 | 13 | for device in platform.get_devices(): 14 | print(' ' + '-' * 56) 15 | print(' Device - Name: ' \ 16 | + device.name) 17 | print(' Device - Type: ' \ 18 | + cl.device_type.to_string(device.type)) 19 | print(' Device - Max Clock Speed: {0} Mhz'\ 20 | .format(device.max_clock_frequency)) 21 | print(' Device - Compute Units: {0}'\ 22 | .format(device.max_compute_units)) 23 | print(' Device - Local Memory: {0:.0f} KB'\ 24 | .format(device.local_mem_size/1024.0)) 25 | print(' Device - Constant Memory: {0:.0f} KB'\ 26 | .format(device.max_constant_buffer_size/1024.0)) 27 | print(' Device - Global Memory: {0:.0f} GB'\ 28 | .format(device.global_mem_size/1073741824.0)) 29 | print(' Device - Max Buffer/Image Size: {0:.0f} MB'\ 30 | .format(device.max_mem_alloc_size/1048576.0)) 31 | print(' Device - Max Work Group Size: {0:.0f}'\ 32 | .format(device.max_work_group_size)) 33 | print('\n') 34 | 35 | if __name__ == "__main__": 36 | print_device_info() 37 | 38 | 39 | -------------------------------------------------------------------------------- /Chapter08/PyOpenCL/elementwisePyopencl.py: -------------------------------------------------------------------------------- 1 | import pyopencl as cl 2 | import pyopencl.array as cl_array 3 | import numpy as np 4 | 5 | context = cl.create_some_context() # Initialize the Context 6 | queue = cl.CommandQueue(context) # Instantiate a Queue 7 | 8 | vector_dimension = 100 9 | vector_a = cl_array.to_device(queue, np.random.randint(vector_dimension, size=vector_dimension)) 10 | vector_b = cl_array.to_device(queue, np.random.randint(vector_dimension, size=vector_dimension)) 11 | result_vector = cl_array.empty_like(vector_a) 12 | 13 | elementwiseSum = cl.elementwise.ElementwiseKernel(context, "int *a, int *b, int *c", "c[i] = a[i] + b[i]", "sum") 14 | elementwiseSum(vector_a, vector_b, result_vector) 15 | 16 | print ("PyOpenCL ELEMENTWISE SUM OF TWO VECTORS") 17 | print ("VECTOR LENGTH = %s" %vector_dimension) 18 | print ("INPUT VECTOR A") 19 | print (vector_a) 20 | print ("INPUT VECTOR B") 21 | print (vector_b) 22 | print ("OUTPUT VECTOR RESULT A + B ") 23 | print (result_vector) 24 | -------------------------------------------------------------------------------- /Chapter08/PyOpenCL/testApplicationPyopencl.py: -------------------------------------------------------------------------------- 1 | from time import time # Import time tools 2 | 3 | import pyopencl as cl 4 | import numpy as np 5 | import deviceInfoPyopencl as device_info 6 | import numpy.linalg as la 7 | 8 | #input vectors 9 | a = np.random.rand(10000).astype(np.float32) 10 | b = np.random.rand(10000).astype(np.float32) 11 | 12 | def test_cpu_vector_sum(a, b): 13 | c_cpu = np.empty_like(a) 14 | cpu_start_time = time() 15 | for i in range(10000): 16 | for j in range(10000): 17 | c_cpu[i] = a[i] + b[i] 18 | cpu_end_time = time() 19 | print("CPU Time: {0} s".format(cpu_end_time - cpu_start_time)) 20 | return c_cpu 21 | 22 | def test_gpu_vector_sum(a, b): 23 | #define the PyOpenCL Context 24 | platform = cl.get_platforms()[0] 25 | device = platform.get_devices()[0] 26 | context = cl.Context([device]) 27 | queue = cl.CommandQueue(context, \ 28 | properties=cl.command_queue_properties.PROFILING_ENABLE) 29 | #prepare the data structure 30 | a_buffer = cl.Buffer\ 31 | (context, cl.mem_flags.READ_ONLY | cl.mem_flags.COPY_HOST_PTR, hostbuf=a) 32 | b_buffer = cl.Buffer\ 33 | (context, cl.mem_flags.READ_ONLY | cl.mem_flags.COPY_HOST_PTR, hostbuf=b) 34 | c_buffer = cl.Buffer\ 35 | (context, cl.mem_flags.WRITE_ONLY, b.nbytes) 36 | program = cl.Program(context, """ 37 | __kernel void sum(__global const float *a, __global const float *b, __global float *c) 38 | { 39 | int i = get_global_id(0); 40 | int j; 41 | for(j = 0; j < 10000; j++) 42 | { 43 | c[i] = a[i] + b[i]; 44 | } 45 | }""").build() 46 | #start the gpu test 47 | gpu_start_time = time() 48 | event = program.sum(queue, a.shape, None, a_buffer, b_buffer, c_buffer) 49 | event.wait() 50 | elapsed = 1e-9*(event.profile.end - event.profile.start) 51 | print("GPU Kernel evaluation Time: {0} s".format(elapsed)) 52 | c_gpu = np.empty_like(a) 53 | cl._enqueue_read_buffer(queue, c_buffer, c_gpu).wait() 54 | gpu_end_time = time() 55 | print("GPU Time: {0} s".format(gpu_end_time - gpu_start_time)) 56 | return c_gpu 57 | 58 | #start the test 59 | if __name__ == "__main__": 60 | #print the device info 61 | device_info.print_device_info() 62 | #call the test on the cpu 63 | cpu_result = test_cpu_vector_sum(a, b) 64 | #call the test on the gpu 65 | gpu_result = test_gpu_vector_sum(a, b) 66 | assert (la.norm(cpu_result - gpu_result)) < 1e-5 67 | 68 | -------------------------------------------------------------------------------- /Chapter08/PyOpenCL/vectorSumPyopencl.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import pyopencl as cl 3 | import numpy.linalg as la 4 | 5 | vector_dimension = 100 6 | 7 | vector_a = np.random.randint(vector_dimension, size=vector_dimension) 8 | vector_b = np.random.randint(vector_dimension, size=vector_dimension) 9 | 10 | platform = cl.get_platforms()[0] 11 | device = platform.get_devices()[0] 12 | context = cl.Context([device]) 13 | queue = cl.CommandQueue(context) 14 | 15 | mf = cl.mem_flags 16 | a_g = cl.Buffer(context, mf.READ_ONLY | mf.COPY_HOST_PTR, hostbuf=vector_a) 17 | b_g = cl.Buffer(context, mf.READ_ONLY | mf.COPY_HOST_PTR, hostbuf=vector_b) 18 | 19 | 20 | program = cl.Program(context, """ 21 | __kernel void vectorSum(__global const int *a_g, __global const int *b_g, __global int *res_g) { 22 | int gid = get_global_id(0); 23 | res_g[gid] = a_g[gid] + b_g[gid]; 24 | } 25 | """).build() 26 | 27 | res_g = cl.Buffer(context, mf.WRITE_ONLY, vector_a.nbytes) 28 | 29 | program.vectorSum(queue, vector_a.shape, None, a_g, b_g, res_g) 30 | 31 | res_np = np.empty_like(vector_a) 32 | cl.enqueue_copy(queue, res_np, res_g) 33 | 34 | print ("PyOPENCL SUM OF TWO VECTORS") 35 | print ("Platform Selected = %s" %platform.name ) 36 | print ("Device Selected = %s" %device.name) 37 | print ("VECTOR LENGTH = %s" %vector_dimension) 38 | print ("INPUT VECTOR A") 39 | print (vector_a) 40 | print ("INPUT VECTOR B") 41 | print (vector_b) 42 | print ("OUTPUT VECTOR RESULT A + B ") 43 | print (res_np) 44 | 45 | assert(la.norm(res_np - (vector_a + vector_b))) < 1e-5 46 | 47 | 48 | -------------------------------------------------------------------------------- /Chapter09/codes chapter 9 debug and test/__pycache__/testset.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Python-Parallel-Programming-Cookbook-Second-Edition/a10f0b2ba69995a6a8697e68ae0b53a20f4c04c7/Chapter09/codes chapter 9 debug and test/__pycache__/testset.cpython-36.pyc -------------------------------------------------------------------------------- /Chapter09/codes chapter 9 debug and test/__pycache__/testset1.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Python-Parallel-Programming-Cookbook-Second-Edition/a10f0b2ba69995a6a8697e68ae0b53a20f4c04c7/Chapter09/codes chapter 9 debug and test/__pycache__/testset1.cpython-36.pyc -------------------------------------------------------------------------------- /Chapter09/codes chapter 9 debug and test/nosetest.py: -------------------------------------------------------------------------------- 1 | from math import * 2 | import nose 3 | 4 | 5 | def add(num1, num2): 6 | assert type(num1) == int or type(num1) == float 7 | assert type(num2) == int or type(num2) == float 8 | return num1 + num2 9 | 10 | def divide(numerator, denominator): 11 | return numerator / denominator 12 | 13 | def test_add_integers(): 14 | assert add(5, 3) == 8 15 | 16 | def test_add_integers_zero(): 17 | assert add(3, 0) == 3 18 | 19 | def test_add_floats(): 20 | assert add(1.5, 2.5) == 4 21 | 22 | def test_add_strings(): 23 | nose.tools.assert_raises(AssertionError, add, 'paul', 'carol') 24 | 25 | def test_divide_integers_even(): 26 | assert divide(2, 10) == 0.2 27 | 28 | def test_divide_integers_repetant(): 29 | nose.tools.assert_almost_equal(divide(1, 3), 0.33333333, 7) 30 | 31 | if __name__ == '__main__': 32 | nose.run() 33 | -------------------------------------------------------------------------------- /Chapter09/codes chapter 9 debug and test/pdb/__pycache__/pdb_test.cpython-35.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Python-Parallel-Programming-Cookbook-Second-Edition/a10f0b2ba69995a6a8697e68ae0b53a20f4c04c7/Chapter09/codes chapter 9 debug and test/pdb/__pycache__/pdb_test.cpython-35.pyc -------------------------------------------------------------------------------- /Chapter09/codes chapter 9 debug and test/pdb/inside_code_to_debug_pdb.py: -------------------------------------------------------------------------------- 1 | import pdb 2 | 3 | class Pdb_test(object): 4 | 5 | def __init__(self, parameter): 6 | self.counter = parameter 7 | 8 | def go(self): 9 | for j in range(self.counter): 10 | pdb.set_trace() 11 | print ("--->",j) 12 | return 13 | 14 | if __name__ == '__main__': 15 | Pdb_test(10).go() 16 | -------------------------------------------------------------------------------- /Chapter09/codes chapter 9 debug and test/pdb/pdb_test.py: -------------------------------------------------------------------------------- 1 | class Pdb_test(object): 2 | def __init__(self, parameter): 3 | self.counter = parameter 4 | 5 | def go(self): 6 | for j in range(self.counter): 7 | print ("--->",j) 8 | return 9 | 10 | if __name__ == '__main__': 11 | Pdb_test(10).go() 12 | -------------------------------------------------------------------------------- /Chapter09/codes chapter 9 debug and test/pdb/postmortem.py: -------------------------------------------------------------------------------- 1 | import pdb 2 | pdb.pm() 3 | -------------------------------------------------------------------------------- /Chapter09/codes chapter 9 debug and test/pdb/unittest_fail.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | 3 | class OutcomesTest(unittest.TestCase): 4 | def testPass(self): 5 | return 6 | def testFail(self): 7 | self.failIf(True) 8 | def testError(self): 9 | raise RuntimeError('test error!') 10 | 11 | if __name__ == '__main__': 12 | unittest.main() -------------------------------------------------------------------------------- /Chapter09/codes chapter 9 debug and test/pdb/using_python_interpreter_pdb.py: -------------------------------------------------------------------------------- 1 | import pdb_test 2 | import pdb 3 | 4 | pdb.run('pdb_test.Pdb_test(10).go()') 5 | 6 | -------------------------------------------------------------------------------- /Chapter09/codes chapter 9 debug and test/rpdb_code_example.py: -------------------------------------------------------------------------------- 1 | import threading 2 | import rpdb 3 | 4 | #debugger = rpdb.Rpdb(port=4444) 5 | rpdb.Rpdb().set_trace() 6 | 7 | def my_func(thread_number): 8 | return print('my_func called by thread N°{}'.format(thread_number)) 9 | 10 | def main(): 11 | threads = [] 12 | for i in range(10): 13 | t = threading.Thread(target=my_func, args=(i,)) 14 | threads.append(t) 15 | t.start() 16 | t.join() 17 | 18 | if __name__ == "__main__": 19 | 20 | main() 21 | 22 | -------------------------------------------------------------------------------- /Chapter09/codes chapter 9 debug and test/simplicisticTest.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | 3 | class SimplisticTest(unittest.TestCase): 4 | 5 | def test(self): 6 | self.assertTrue(True) 7 | 8 | if __name__ == '__main__': 9 | unittest.main() 10 | -------------------------------------------------------------------------------- /Chapter09/codes chapter 9 debug and test/testset.py: -------------------------------------------------------------------------------- 1 | #testset.py 2 | from nose.tools import eq_ 3 | import unittest 4 | 5 | 6 | class TestSuite: 7 | def test_mult(self): 8 | eq_(2*2,4) 9 | 10 | def ignored(self): 11 | eq_(2*2,3) -------------------------------------------------------------------------------- /Chapter09/codes chapter 9 debug and test/testset1.py: -------------------------------------------------------------------------------- 1 | #testset.py 2 | from nose.tools import eq_ 3 | import unittest 4 | 5 | 6 | def test_sum(): 7 | eq_(2+2,4) 8 | -------------------------------------------------------------------------------- /Chapter09/codes chapter 9 debug and test/unittest_exception.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | 3 | def raises_error(*args, **kwds): 4 | print (args, kwds) 5 | raise ValueError\ 6 | ('Valore non valido:'+ str(args)+ str(kwds)) 7 | 8 | class ExceptionTest(unittest.TestCase): 9 | def testTrapLocally(self): 10 | try: 11 | raises_error('a', b='c') 12 | except ValueError: 13 | pass 14 | else: 15 | self.fail('Non si vede ValueError') 16 | 17 | def testFailUnlessRaises(self): 18 | self.assertRaises\ 19 | (ValueError, raises_error, 'a', b='c') 20 | 21 | if __name__ == '__main__': 22 | unittest.main() -------------------------------------------------------------------------------- /Chapter09/codes chapter 9 debug and test/unittest_truth.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | 3 | class TruthTest(unittest.TestCase): 4 | 5 | def testFailUnless(self): 6 | self.failUnless(True) 7 | def testAssertTrue(self): 8 | self.assertTrue(True) 9 | def testFailIf(self): 10 | self.assertFalse(False) 11 | def testAssertFalse(self): 12 | self.assertFalse(False) 13 | if __name__ == '__main__': 14 | unittest.main() -------------------------------------------------------------------------------- /Chapter09/codes chapter 9 debug and test/winpdb_reborn_code_example.py: -------------------------------------------------------------------------------- 1 | import time 2 | import os 3 | from random import randint 4 | from threading import Thread 5 | 6 | class MyThreadClass (Thread): 7 | def __init__(self, name, duration): 8 | Thread.__init__(self) 9 | self.name = name 10 | self.duration = duration 11 | def run(self): 12 | print ("---> " + self.name + \ 13 | " running, belonging to process ID "\ 14 | + str(os.getpid()) + "\n") 15 | time.sleep(self.duration) 16 | print ("---> " + self.name + " over\n") 17 | 18 | 19 | def main(): 20 | start_time = time.time() 21 | 22 | # Thread Creation 23 | thread1 = MyThreadClass("Thread#1 ", randint(1,10)) 24 | thread2 = MyThreadClass("Thread#2 ", randint(1,10)) 25 | thread3 = MyThreadClass("Thread#3 ", randint(1,10)) 26 | 27 | # Thread Running 28 | thread1.start() 29 | thread2.start() 30 | thread3.start() 31 | 32 | # Thread joining 33 | thread1.join() 34 | thread2.join() 35 | thread3.join() 36 | 37 | # End 38 | print("End") 39 | 40 | #Execution Time 41 | print("--- %s seconds ---" % (time.time() - start_time)) 42 | 43 | 44 | if __name__ == "__main__": 45 | main() 46 | 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Packt 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Python Parallel Programming Cookbook - Second Edition 2 | 3 | Python Parallel Programming Cookbook - Second Edition 4 | 5 | This is the code repository for [Python Parallel Programming Cookbook - Second Edition ](https://www.packtpub.com/programming/python-parallel-programming-cookbook?utm_source=github&utm_medium=repository&utm_campaign=9781789533736), published by Packt. 6 | 7 | **Over 70 recipes to solve challenges in multithreading and distributed system with Python 3** 8 | 9 | ## What is this book about? 10 | Nowadays, it has become extremely important for programmers to understand the link between the software and the parallel nature of their hardware so that their programs run efficiently on computer architectures. Applications based on parallel programming are fast, robust, and easily scalable. 11 | 12 | 13 | This book covers the following exciting features: 14 | * Synchronize multiple threads and processes to manage parallel tasks 15 | * Use message passing techniques to establish communication between processes to build parallel applications 16 | * Program your own GPU cards to address complex problems 17 | * Manage computing entities to execute distributed computational task 18 | * Write efficient programs by adopting the event-driven programming model 19 | * Explore cloud technology with Django and Google App Engine 20 | * Apply parallel programming techniques that can lead to performance improvements 21 | 22 | If you feel this book is for you, get your [copy](https://www.amazon.com/dp/1789533732) today! 23 | 24 | https://www.packtpub.com/ 26 | 27 | ## Instructions and Navigations 28 | All of the code is organized into folders. For example, Chapter02. 29 | 30 | The code will look like the following: 31 | ``` 32 | class Pdb_test(object): 33 | def __init__(self, parameter): 34 | self.counter = parameter 35 | ``` 36 | 37 | **Following is what you need for this book:** 38 | The Python Parallel Programming Cookbook is for software developers who are well-versed with Python and want to use parallel programming techniques to write powerful and efficient code. This book will help you master the basics and the advanced of parallel computing. 39 | 40 | With the following software and hardware list you can run all code files present in the book (Chapter 01-09). 41 | ### Software and Hardware List 42 | | No | Software required | OS required | 43 | | -------- | ------------------------------------ | ----------------------------------- | 44 | | 1 | Python 3.7 | Any | 45 | 46 | 47 | We also provide a PDF file that has color images of the screenshots/diagrams used in this book. [Click here to download it](https://static.packt-cdn.com/downloads/9781789533736_ColorImages.pdf). 48 | 49 | ### Related products 50 | * Mastering GUI Programming with Python [[Packt]](https://www.packtpub.com/in/application-development/mastering-gui-programming-python?utm_source=github&utm_medium=repository&utm_campaign=9781789612905) [[Amazon]](https://www.amazon.com/dp/178961290X) 51 | 52 | * Expert Python Programming - Third Edition [[Packt]](https://www.packtpub.com/in/application-development/expert-python-programming-third-edition?utm_source=github&utm_medium=repository&utm_campaign=9781789808896) [[Amazon]](https://www.amazon.com/dp/1789808898) 53 | 54 | ## Get to Know the Author 55 | **Giancarlo Zaccone** 56 | Giancarlo Zaccone has over fifteen years' experience of managing research projects in the scientific and industrial domains. He is a software and systems engineer at the European Space Agency (ESTEC), where he mainly deals with the cybersecurity of satellite navigation systems. 57 | 58 | Giancarlo holds a master's degree in physics and an advanced master's degree in scientific computing. 59 | 60 | Giancarlo has already authored the following titles, available from Packt: Python Parallel Programming Cookbook (First Edition), Getting Started with TensorFlow, Deep Learning with TensorFlow (First Edition), and Deep Learning with TensorFlow (Second Edition). 61 | 62 | ## Other books by the authors 63 | [Python Parallel Programming Cookbook ](https://www.packtpub.com/application-development/python-parallel-programming-cookbook?utm_source=github&utm_medium=repository&utm_campaign=9781785289583) 64 | 65 | ### Suggestions and Feedback 66 | [Click here](https://docs.google.com/forms/d/e/1FAIpQLSdy7dATC6QmEL81FIUuymZ0Wy9vH1jHkvpY57OiMeKGqib_Ow/viewform) if you have any feedback or suggestions. 67 | 68 | --------------------------------------------------------------------------------