Scoping in loops and multi-threading

Hello everyone,
I just started using multi-threading, and have a basic question about multi-threading with loops. This might be a bit of a duplicate on some other questions here (like this: PSA: Reasoning about scope rules and multithreading) but I was still a bit confused. It would be great to get some advice on this!

Here is a rough outline of the code I’m running:

@threads for i = 1:N
data = full_data[agent_id .== i,:] 
# thus subset of data used varies by iterations
iter = 1.0
tol = 1e6

   while ( (iter < 5000) && (tol > 1e-8) )
    #-----some code here using data subset --------#
    #-----create new_vec------#

    tol = norm(new_vec - old_vec)
    iter = iter + 1
   end

end

You can think that within each iteration of the for-loop, I’m running a while loop. In each iteration of the while loop, I’m creating a vector called new_vec, and comparing that with the previous while-loop’s created vector (old_vec). If the difference is small enough, I stop the while-loop, and move on to the next iteration of for-loop. Note that I am not writing to data or full_data, I just use them to create new_vec.

I’m multi-threading the for-loop. Each iteration of the for-loop does not depend on other iterations, i.e. new_vec for i = 100 doesn’t influence new_vec for i = 500.

My worry is that if I do this, then there could be some sort of data race being created for iter and tol. That is, the value of iter in one i could end up in the value of iter in another i, and similarly for tol. Is this an issue? Or are the scopes here somehow for-loop iteration specific, i.e. tol and iter in each iteration of for-loop is untouched by others?

I also did the following but I’m not sure if it would help.

@threads for i = 1:N
data = full_data[agent_id .== i,:] 
# thus subset of data used varies by iterations
local iter = 1.0
local tol = 1e6

   while ( (iter < 5000) && (tol > 1e-8) )
    #-----some code here using data subset --------#
    #-----create new_vec------#

    tol = norm(new_vec - old_vec)
    iter = iter + 1
   end

end

Does putting in the local at the beginning limit the scope of tol and iter to that specific for-loop iteration?
Any suggestions on how to improve the code would be appreciated too. Thanks!

that is true even without multithreading

their scope is already local to each iteration of the loop. You probably want to add a local old_vec, beause the same is valid to the iterations of the while loop, and if you do not add local old_vec (or initialize it with a value) outside that while loop, its value won’t be preserved from one iteration to the other.

2 Likes