
This slowdown was found with one of my favorite benchmarks, which is calculating the pi value with the Monte Carlo method.
importosimportrandomimporttimefromthreadingimportThreaddefmonte_carlo_pi_part(n: int, idx: int, results: list[int]) ->None:
count=0foriinrange(n):
x=random.random()
y=random.random()
ifx*x+y*y<=1:
count+=1results[idx] =countn=10000threads= []
num_threads=100results= [0] *num_threadsa=time.time()
foriinrange(num_threads):
t=Thread(target=monte_carlo_pi_part, args=(n, i, results))
t.start()
threads.append(t)
whilethreads:
t=threads.pop()
t.join()
b=time.time()
print(sum(results) / (n*num_threads) *4)
print(b-a)
Acquiring critical sections for random methods causes this slowdown.
Removing @critical_section from the method, which uses genrand_uint32 and then updating genrand_uint32 to use atomic operation makes the performance acceptable.
| Build | Elapsed | PI |
|---|
| Default (with specialization) | 0.16528010368347168 | 3.144508 |
| Free-threading (with no specialization) | 0.548654317855835 | 3.1421 |
| Free-threading with my patch (with no specialization) | 0.2606849670410156 | 3.141108 |
Linked PRs
This slowdown was found with one of my favorite benchmarks, which is calculating the pi value with the Monte Carlo method.
Acquiring critical sections for random methods causes this slowdown.
Removing
@critical_sectionfrom the method, which usesgenrand_uint32and then updatinggenrand_uint32to use atomic operation makes the performance acceptable.Linked PRs