I am trying to write threaded code for the following calculation:
- 
given an opaque object x, and indices i, calculate y_i = g(x, i), 
- 
given each y_i and indices j, calculate {z_i}_j = h(x, y_i, j), 
- 
reduce all the z's with a bivariate function r, which is commutative and associative. 
Here is the single-threaded MWE, I would appreciate some help with making this multi-threaded.
### elements of the the calculation
g(x, i) = (; x, i)              # y_i = g(x, i)
function h(x, g_xi, j)          # z_i_j = h(x, g(x, i), j)
    (; i) = g_xi
    sleep(rand() / 100)
    Dict((x, i, j) => "$(i)_$(j)")
end
r(a, b) = merge(a, b)           # merge z_i_j
# single-threaded implementation
function single_threaded(g, h, r, x, all_i, all_j)
    function inner(i)
        g_xi = g(x, i)
        mapreduce(j -> h(x, g_xi, j), r, all_j)
    end
    mapreduce(inner, r, all_i)
end
# example
ALL_I = 1970:1980
ALL_J = 1:24
single = single_threaded(g, h, r, nothing, ALL_I, ALL_J)