Threads are good for parallelizing in/out operation, eg. when you are waiting for a response from a socket, then you can do some useful stuff in other threads and thus reduce execution time. But if you have really exhausting operation, which consumes the whole CPU, then the threading will be even slower, because you have some overhead switching between threads.
Here is a slightly modified example, but instead of expensive operation x**x, there is only sleep and the result is as expected.
from threading import Thread
from time import time, sleep
LOOPS = 10
TASKS = 5
SLEEP = 0.1
def task():
for _ in range(LOOPS):
sleep(SLEEP)
def timing(func):
def wrapper():
start = time()
func()
duration = time() - start
print(duration)
return wrapper
@timing
def serial():
print("serial execution")
for _ in range(TASKS):
task()
@timing
def paralel():
print("paralel execution")
threads = []
for _ in range(TASKS):
t = Thread(target=task)
threads.append(t)
t.start()
for t in threads:
t.join()
def main():
serial()
paralel()
if __name__ == "__main__":
main()
serial execution
5.0098230838775635
paralel execution
1.0120694637298584