I was experimenting with pythons multiprocessing and threading modules and, stumbled upon something rather strange.
have a look at the following program:
import threading
import time
import multiprocessing
target_count = int(100e6)
mutex = threading.Lock()
def thread_fn(thread_count):
y = 0
for i in range(target_count // thread_count):
y += 1
x = 0
start = time.time()
for i in range(target_count):
x += 1
end = time.time()
print(f"single thread time: {(end - start) * 1000}ms")
thread_count = 1
trds = []
start = time.time()
for i in range(thread_count):
t = threading.Thread(target=thread_fn, args=(thread_count, ))
t.start()
trds.append(t)
for i in range(thread_count):
trds[i].join()
end = time.time()
print(f"{thread_count} threads time: {(end - start) * 1000}ms")
Main thread increments variable until it reaches target_count, similarly opened single thread function thread_fn() increments a local variable.
I was expecting them to be around the same value but, the result I get from running this code is:
single thread time: 9375.770568847656ms
1 threads time: 5802.408456802368ms
Is this due to erroneous code or is something weird about GIL happening?
Also, if I set thread_count=8 change the thread_fn() program as follows (I know that using mutex here is non-sensical but I happen to have left it there accidentally):
def thread_fn(thread_count):
y = 0
with mutex:
for i in range(target_count // thread_count):
y += 1
running the program gives:
single thread time: 10064.738273620605ms
8 threads time: 6456.046581268311ms
Why with the addition of mutex i get a speed boost? I was expecting it to be slower due to unnecessary locking and unlocking since as far as i know because of GIL threads run sequentially.
and without using mutex and using 8 threads:
single thread time: 10910.805225372314ms
8 threads time: 13055.136442184448ms
thread_fn()by having it do nothing at all except immediately return.