Python Συνταγή 3 – Δουλεύοντας με Processes

Στο προηγούμενο post είδαμε πώς μπορούμε να δουλέψουμε στην Python με threads και να επιταχύνουμε την εκτέλεση των προγραμμάτων μας. Σε αυτό το post θα δούμε την δεύτερη επιλογή που μας δίνει η Python για παράλληλους υπολογισμούς μέσω του multiprocessing module.

Σε αντίθεση με τα threads κάθε καινούριο process ξεκινάει ανεξάρτητα από το πρώτο process. Για τον λόγο αυτό η εκκίνηση ενός process είναι πιο χρονοβόρα από την εκκίνηση ενός thread. Η μνήμη του υπολογιστή δεν διαμοιράζεται μεταξύ των processes ενώ τέλος υπάρχει ένα GIL (Global Interpreter Lock ) για κάθε process.

Θα υλοποιήσουμε το παράδειγμα του προηγούμενου post αλλά αυτή τη φορά με processes . Και φυσικά θα συγκρίνουμε την ταχύτητα με τον ίδιο ακριβώς τρόπο.

Παρακάτω μπορείτε να δείτε το script :

from multiprocessing import Process
import os
import math
import time

def calc():
    for i in range(0,9000000):
        math.sqrt(i)

#Για να αποφύγουμε την αναδρομική δημιουργία processes στα windows βάζουμε
#την παρακάτω γραμμή κώδικα οπου εξασφαλίζουμε την εκτέλεση του main module στην αρχή
if __name__ == '__main__':
    timeStart = time.time()
    process_list = []

    for i in range(os.cpu_count()):
        print('Καταχώρηση Process Νο: %d' %i)    
        process_list.append(Process(target=calc))

    for process in process_list:
        process.start()

    for process in process_list:
        process.join()

    timeEnd = time.time()
    totalTime = timeEnd-timeStart
    #Τυπώνουμε πόσα δευτερόλεπτα πήρε η εκτέλεση του προγράμματος
    print("Συνολικός Χρόνος Εκτέλεσης σε δευτερόλεπτα : "+str(totalTime))

Η λογική είναι ακριβώς ίδια με τα threads. Αφού φορτώσουμε το σωστό module καταχωρούμε τα processes και τα ξεκινάμε και τα κάνουμε join με τον ίδιο ακριβώς τρόπο. Εαν τρέχετε τον κώδικα σε windows θα πρέπει να εσωκλείσετε την εκτέλεση στη main κάτι το οποίο γίνεται με την παρακάτω γραμμή :

if name == ‘main‘:

Διαφορετικά το πρόγραμμα θα κρασάρει μιας και θα δημιουργεί συνέχεια processes. Μπορείτε να το δοκιμάσετε για να το διαπιστώσετε.

Παρακάτω βλέπουμε πώς ο χρόνος εκτέλεσης είναι στα 2.8 δευτερόλεπτα δλδ σχεδόν 4 φορές γρηγορότερη εκτέλεση από την υλοποίηση με threads.

Moras@DESKTOP-E1B009K MINGW64 /e/Dropbox/PROJECTS/PYTHON/python-recipes/processes (master)
$ python processes.py
Καταχώρηση Process Νο: 0
Καταχώρηση Process Νο: 1
Καταχώρηση Process Νο: 2
Καταχώρηση Process Νο: 3
Συνολικός Χρόνος Εκτέλεσης σε δευτερόλεπτα : 2.854192018508911

Αυτό δεν σημαίνει όμως πώς πρέπει πάντα χρησιμοποιούμε processes αλλά ανάλογα με την περίπτωση επιλέγουμε την αντίστοιχη λύση

Τέλος ο κώδικας της εφαρμογής είναι στο github στο παρακάτω link
https://github.com/delmoras/python-recipes/tree/master/processes