Hi all, hoping someone here can help me answer a MultiThreaded problem I am having.
Here is my code:
n = 10000000;
numprimes = Threads.Atomic{Int}(0);
function is_prime(n)
if n == 0 | n == 1
return 0
elseif n == 2
return 1
end
root_n = isqrt(n)
for i = 2:root_n
if n%i == 0
return 0
end
end
return 1
end
function main()
Threads.@threads for i = 1:n
if is_prime(i) == 1
global numprimes = atomic_add!(numprimes, 1)
end
end
end
main()
I am getting this error when trying to use a Threads.@Atomic variable to collect numprimes
:
Error thrown in threaded loop on thread 0: MethodError(f=typeof(Base.:(+))(), args=(Base.Threads.Atomic{Int64}(value=0), 1), world=0x00000000000063ec)Thread ID:
1
And I can’t find something online to help me figure out how to solve this.
Would anyone have some insight on what I should change in my code?
Many thanks!
Remove the global numprimes =
from inside the loop. atomic_add! returns the OLD value. so really you are changing numprimes to an Int
the first time in the loop, then trying to do an atomic_add on an int
rather than an atomic value.
However I think the actual error you are getting is that you have multiple threads trying to update a global variable (and change it’s type) and I don’t think Julia is happy about that.
global turned out not to be the problem, global needed to be there so it could be incremented and saved/ accessed properly later.
The problem was I was calling atomic_add!
rather than Theads.atomic_add!
, which gives the correct output.
I also changed my variable numprimes
at the very top to equal 0
, and I modified my for loop
to:
function main()
threadprimes = Threads.Atomic{Int}(0)
Threads.@threads for i = 1:n
if is_prime(i) == 1
global numprimes = Threads.atomic_add!(threadprimes, 1)
end
end
end
Thank you for your reply though! I appreciate it.
function main()
threadprimes = Threads.Atomic{Int}(0)
Threads.@threads for i = 1:n
if is_prime(i) == 1
Threads.atomic_add!(threadprimes, 1)
end
end
global numprimes = threadprimes[]
end
I think that would be better. The original function has a small race condition:
- Thread 1 increments threadprimes to 10.
- Thread 2 increments threadprimes to 11.
- Thread 2 sets numprimes to 11.
- Thread 1 sets numprimes to 10.
Which you would only see if it happen at the very end, but still.
1 Like
Hi pixel27,
You are right - I just modified my code and it still gives the correct output on all threads. Thank you! This is the correct answer. I’m sorry if that is what you were trying to clarify originally in your previous response, as well.
1 Like