Reputation: 75
I am just learning the threading module of python, threading implementation of a test code as below takes more time compared to the sequential implementation. Am I missing an underlying concept of threading in python?
from time import sleep, perf_counter
from threading import Thread
def task(id):
print(f'Starting the task {id}...')
for i in range(1, 1000):
for j in range(1, 1000):
b=(i**2)/(i*j**3)
print(f'The task {id} completed')
############## sequential ##############
start_time = perf_counter()
for n in range(1, 11):
task(n)
end_time = perf_counter()
print(f'sequential took {end_time- start_time: f} second(s) to complete.')
##########E Multi-threading ##########
start_time = perf_counter()
threads = []
for n in range(1, 11):
t = Thread(target=task, args=(n,))
threads.append(t)
t.start()
for t in threads:
t.join()
end_time = perf_counter()
print(f'multi-threaded took {end_time- start_time: f} second(s) to complete.')
Upvotes: 0
Views: 569
Reputation: 1408
I think your threading solution looks nice and correct but there is a pitfal of using threading
in python as it is still using a single core. Check this tutorial which I find really helpful to understand why: https://www.quantstart.com/articles/Parallelising-Python-with-Threading-and-Multiprocessing/
The essence from that resource:
The GIL is necessary because the Python interpreter is not thread safe. This means that there is a globally enforced lock when trying to safely access Python objects from within threads. At any one time only a single thread can acquire a lock for a Python object or C API. The interpreter will reacquire this lock for every 100 bytecodes of Python instructions and around (potentially) blocking I/O operations. Because of this lock CPU-bound code will see no gain in performance when using the Threading library, but it will likely gain performance increases if the Multiprocessing library is used.
In other words: Use multiprocessing instead.
Upvotes: 1