You may want to take a look at examples/plife.jl that implements the Game
of Life on a distributed array - sounds quite similar to your problem.
-viral
On Sunday, August 31, 2014 5:35:57 AM UTC+5:30, Spencer Lyon wrote:
>
> I often solve fixed point problems where I apply a contraction mapping to
> an array and`` iterate until convergence. There is nothing in the algorithm
> that requires the new value at one array index to depend on neighboring
> indices — only on values obtained at the same index on the previous
> iteration.
>
> It should be quite easy to parallelize each iteration of this algorithm.
> My question is what the optimal strategy would be for parallelizing the
> algorithm using the built-in Julia features. If I were using MPI I would
> simply assign each process a chunk of indices and let them update that
> portion of the array on each iteration. Would a similar approach be optimal
> in Julia also? If so, how would I do that? If not, what would be better?
>
> To give you an idea of the type of algorithm I am talking about, I have
> included a working example below (it requires Grid.jl and Optim.jl). I
> realize that there is a lot of code below, so if it is too long to expect
> people on this forum to read, please let me know and I will try to condense
> my code. Thanks!
>
> using Grid
> using Optim
> #=
> Computes and returns T^k v, where T is an operator, v is an initial
> condition and k is the number of iterates. Provided that T is a
> contraction mapping or similar, T^k v will be an approximation to
> the fixed point.
> =#
> function compute_fixed_point(T::Function, v; err_tol=1e-3, max_iter=50,
> verbose=true, print_skip=10)
> iterate = 0
> err = err_tol + 1
> while iterate < max_iter && err > err_tol
> new_v = T(v)
> iterate += 1
> err = Base.maxabs(new_v - v)
> if verbose
> if iterate % print_skip == 0
> println("Compute iterate $iterate with error $err")
> end
> end
> v = new_v
> end
>
> if iterate < max_iter && verbose
> println("Converged in $iterate steps")
> elseif iterate == max_iter
> warn("max_iter exceeded in compute_fixed_point")
> end
>
> return v
> end
>
> linspace_range(x_min, x_max, n_x) = x_min:(x_max - x_min) / (n_x - 1): x_max
>
> type GrowthModel
> f::Function
> bet::Real
> u::Function
> grid_max::Int
> grid_size::Int
> grid::FloatRange
> end
>
> default_f(k) = k^0.65
> default_u(c) = log(c)
>
> function GrowthModel(f=default_f, bet=0.95, u=default_u,
> grid_max=2, grid_size=150)
> grid = linspace_range(1e-6, grid_max, grid_size)
> return GrowthModel(f, bet, u, grid_max, grid_size, grid)
> end
>
> #=
> The approximate Bellman operator, which computes and returns the
> updated value function Tw on the grid points. Could also return the
> policy function instead if asked.
>
> NOTE: this is the function I would like to parallelize
> =#
> function bellman_operator!(g::GrowthModel, w::Vector, out::Vector;
> ret_policy::Bool=false)
> # Apply linear interpolation to w
> Aw = CoordInterpGrid(g.grid, w, BCnan, InterpLinear)
>
> for (i, k) in enumerate(g.grid)
> objective(c) = - g.u(c) - g.bet * Aw[g.f(k) - c]
> res = optimize(objective, 1e-6, g.f(k))
> c_star = res.minimum
>
> if ret_policy
> # set the policy equal to the optimal c
> out[i] = c_star
> else
> # set Tw[i] equal to max_c { u(c) + beta w(f(k_i) - c)}
> out[i] = - objective(c_star)
> end
> end
>
> return out
> end
>
> function bellman_operator(g::GrowthModel, w::Vector;
> ret_policy::Bool=false)
> out = similar(w)
> bellman_operator!(g, w, out, ret_policy=ret_policy)
> end
>
> gm = GrowthModel()
> v_init = 5 .* gm.u(gm.grid) .- 25
>
> v_star = compute_fixed_point(x->bellman_operator(gm, x), v_init,
> max_iter=1000, err_tol=1e-7)
>
>
>