# L-15 MCS 572 Mon 30 Sep 2024 : worksteal.jl """ Illustrates the work stealing idea to processing job queues by many threads. At the command prompt, type julia -t 4 worksteal.jl to run with four threads. """ using Base.Threads nt = nthreads() println("the number of threads : ", nt) nbr = 10 # number of jobs in each queue # allocate memory for all job queues jobs = [zeros(nbr) for i=1:nt] # every worker generates its own job queue # even indexed queues have light work loads @threads for i=1:nt if i % 2 == 0 jobs[i] = rand((1, 2, 3), nbr) else jobs[i] = rand((4, 5, 6), nbr) end println("Worker ", threadid(), " has jobs ", jobs[i], " ", sum(jobs[i])) end # every job queue has its own index to the next job jobidx = [Atomic{Int}(1) for i=1:nt] @threads for i=1:nt while true myjob = atomic_add!(jobidx[i], 1) if myjob > length(jobs[i]) break end println("Worker ", threadid(), " spends ", jobs[i][myjob], " seconds", " on job ", myjob, " ...") sleep(jobs[i][myjob]) jobs[i][myjob] = threadid() end println("Worker ", threadid(), " will steal jobs ...") more2steal = true while more2steal more2steal = false for j=1:threadid()-1 myjob = atomic_add!(jobidx[j], 1) if myjob <= length(jobs[j]) println("Worker ", threadid(), " spends ", jobs[j][myjob], " seconds", " on job ", myjob, " of ", j, " ...") sleep(jobs[j][myjob]) jobs[j][myjob] = threadid() end more2steal = (myjob < length(jobs[j])) end for j=threadid()+1:nt myjob = atomic_add!(jobidx[j], 1) if myjob <= length(jobs[j]) println("Worker ", threadid(), " spends ", jobs[j][myjob], " seconds", " on job ", myjob, " of ", j, " ...") sleep(jobs[j][myjob]) jobs[j][myjob] = threadid() end more2steal = (myjob < length(jobs[j])) end end end for i=1:nt println("Jobs done : ", jobs[i]) end