Ceci est une ancienne révision du document !
Table des matières
Python: Multiprocessing et GIL
Python est lent et n'est pas multiprocessus
Balivernes … billevesées …
Toutes les Intelligences Artificielles ont une façade en python … Dja dja (ah bon!)
L'interpréteur python est généralement CPython qui est comme son nom l'indique écrit en C, le C serait lent ?
GIL
Le module threading permet de lancer des tâches en parallèles, mais en réalité elles ne le sont pas: tout se fait sur un seul cœur du processeur. Les tâches sont découpées en petits bouts, exécution d'un bout d'une, puis un petit de l'autre, etc …
Le GIL (Global Interpreteur Lock) évite de surcharger un thread.
Le module multiprocessing utilise réellement un cœur pour chaque tâche, et il est possible que chaque tâche communique avec une autre.
Par contre, un processus n'utilise toujours qu'un seul cœur.
Ressources sur le module multiprocessing
Mais comme souvent, les tutos sont hyper-compliqués, les auteurs montrent qu'ils sont très forts avec des exemples inappropriés.
Remarques
Certains modules, tel que numpy, sont déjà multiprocess.
Exemples de Multiprocessing
Je vous propose des exemples simples:
- multiprocessing_example_1.py
""" Exemple d'utilisation de multiprocessing documentation https://docs.python.org/3/library/multiprocessing.html Exemple de 2 processus qui tournent en parallèle sans communiquer. """ import os from multiprocessing import Process from time import sleep def first_processus(): print('first process:', os.getppid()) a = 0 while 1: sleep(1) a += 1 print("a =", a) def second_processus(): print('second process:', os.getppid()) b = 0 while 1: sleep(2) b += 5 print("b =", b) def main(): p = Process(target=second_processus) p.start() first_processus() if __name__ == '__main__': main()
- multiprocessing_example_2.py
""" Exemple de 2 processus qui tournent en parallèle et échangent une variable avec Pipe. https://docs.python.org/3/library/multiprocessing.html#exchanging-objects-between-processes The Pipe() function returns a pair of connection objects connected by a pipe which by default is duplex (two-way). """ import os from multiprocessing import Process, Pipe def test(n): """Fonction pour charger le processeur""" for i in range(n): m = (i ** 1.89999) ** 0.8974125 def first_processus(conn): print('first process:', os.getppid()) a = 0 while 1: test(1000000) a += 1 print("a =", a) b = conn.recv() print("b dans first_process =", b) a += b[1] def second_processus(conn): print('second process:', os.getppid()) b = 0 while 1: test(2000000) b += 5 print("b dans second process =", b) conn.send(['b', b]) def main(): """ https://docs.python.org/3/library/multiprocessing.html#multiprocessing.Pipe multiprocessing.Pipe([duplex]) If duplex is True (the default) then the pipe is bidirectional. If duplex is False then the pipe is unidirectional: conn1 can only be used for receiving messages and conn2 can only be used for sending messages. """ parent_conn, child_conn = Pipe() p = Process(target=second_processus, args=(child_conn,)) p.start() first_processus(parent_conn) if __name__ == '__main__': main()
Multiprocess dans kivy
Une application kivy qui excécute pyrealsense et coral dans un Process avec Pipe marche impeccable.
- sergeLabo personnages3d Détection de 1 à 4 personnes
- Inferface graphique réalisée avec Kivy
- Suivi des personnes devant la caméra
multiprocessing.shared_memory
Ressources
Exemple d'utilisation bas niveau d'instances de SharedMemory
from multiprocessing import shared_memory shm_a = shared_memory.SharedMemory(create=True, size=10) m = shm_a.buf print('type(m)', type(m)) buffer = shm_a.buf print('len(buffer)', len(buffer)) # Modify multiple at once buffer[:4] = bytearray([22, 33, 44, 55]) # Modify single byte at a time buffer[4] = 100 # Attach to an existing shared memory block shm_b = shared_memory.SharedMemory(shm_a.name) import array # Copy the data into a new array.array ar = array.array('b', shm_b.buf[:5]) print('ar', ar) # Modify via shm_b using bytes shm_b.buf[:5] = b'howdy' # Access via shm_a print('bytes(shm_a.buf[:5])', bytes(shm_a.buf[:5])) # Close each SharedMemory instance shm_b.close() shm_a.close() # Call unlink only once to release the shared memory shm_a.unlink()