How to @parallel a CartesianRange?

In serial, the following for loop is just fine:

A = randn(5,5)

for inds = CartesianRange(size(A))
  i, j = inds.I
  # Some function of A[i, j], i, and j
end

However, naively adding @sync @parallel to the for loop throws a MethodError:

ERROR: LoadError: MethodError: no method matching getindex(::CartesianRange{CartesianIndex{2}}, ::UnitRange{Int64})

I assume this is the part of the @parallel macro that subdivides the range into approximately-equal chunklets.

I’ve tried simply adding the relevant getindex definitions, but I can’t settle on a definition that isn’t awful. Thoughts?

I thought about working around the issue by doing something like

@sync @parallel for idx = eachindex(A)
  i, j = ind2sub(size(A), idx)
  # Some function of A[idx], i, and j
end

but in real life A is a pretty large matrix of arbitrary dimension and ind2sub seems expensive relative to the rest of this inner loop.

1 Like