Thank you very much, it was really helpful!

On Tuesday, March 8, 2016 at 1:00:53 AM UTC-6, Tomas Lycken wrote:
>
> The thing with meshgrid, is that it’s terribly inefficient compared to 
> the equivalent idioms in Julia. Instead of implementing it and keeping with 
> inefficient habits, embrace the fact that there are better ways to do 
> things :)
>
> Since this question is recurring, I think the problem might rather be 
> documentation. As a user looking for a meshgrid function, where did you 
> look? What did you look for, more specifically? Would it have helped to 
> have some examples along the lines of “when you want to do this, using 
> meshgrid, in MATLAB, here’s how to do the same thing without meshgrid in 
> Julia”? I could turn the following writeup into a FAQ entry or something, 
> but it would be nice to know where to place it to actually have it make a 
> difference.
> Making do without meshgrid (and getting out ahead!) 
>
> For starters, if what you are after is a straight-up port, meshgrid is 
> *very* easy to implement for yourself, so that you don’t have to think 
> about the rest. *Mind you, this is not the most performant way to do 
> this!*
>
> meshgrid(xs, ys) = [xs[i] for i in 1:length(xs), j in length(ys)], [ys[j] for 
> i in 1:length(xs), j in 1:length(ys)]
>
> Try it out with X, Y = meshgrid(1:15, 1:8). (If you’re not happy with the 
> orientation of the axes, just switch i and j in the meshgrid 
> implementation.)
>
> However, most of the uses of meshgrid in MATLAB is for stuff where you 
> want to do a bunch of calculations for each point on a grid, and where each 
> calculation is dependent on the coordinates of just one point. Usually 
> something along the lines of
>
> X, Y = meshgrid(xs, ys)
> Z = sin(X) + 2 * Y.^2 ./ cos(X + Y)
>
> In Julia, this is better done with a list comprehension altogether, 
> eliminating the need for allocating X and Y:
>
> Z = [sin(x) + 2 * y^2 / cos(x+y) for x in xs, y in ys]
>
> If you think it’s now become too difficult to read what the actual 
> transformation is, just refactor it out into a function:
>
> foo(x,y) = sin(x) + 2 * y^2 / cos(x+y)
> Z = [foo(x,y) for x in xs, y in ys]
>
> If you do this a lot, you might want to avoid writing the list 
> comprehension altogether; that’s easy too. Just create a function that does 
> that for you. With a little clever interface design, you’ll see that this 
> is even more useful than what you could do with meshgrid. 
>
> inflate(f, xs, ys) = [f(x,y) for x in xs, y in ys]
>
> # call version 1: with a named function
> inflate(foo, xs, ys) 
>
> # call version 2: anonymous function syntax
> inflate((x,y) -> sin(x) + 2 * y^2 / cos(x,y), xs, ys)
>
> # call version 3: with a do block
> inflate(xs, ys) do x, y
>     sin(x) + 2 * y^2 / cos(x,y)
> end
>
> Note that the last version of this call is very flexible; in fact, it’s 
> just as flexible as having a named function. For example, you can do 
> everything in multiple steps, allowing for intermediate results that don’t 
> have to allocate large arrays (as they would have, had you used meshgrid), 
> making it easier to be explicit about whatever algorithm you’re using.
>
> However, the two last versions of these calls are not the most performant 
> as of yet, since they’re using anonymous functions. This is changing, 
> though, and in 0.5 this won’t be an issue anymore. Until then, for large 
> arrays I’d use the first call version, with a named function, to squeeze as 
> much as possible out of this.
>
> I did a small benchmark of this using a straight list comprehension (i.e. 
> without the inflate function) vs using meshgrid. Here are the results:
>
> julia> foo(x,y) = sin(x) + 2y.^2 ./ cos(x+y);
>
> julia> function bench_meshgrid(N)
>            X, Y = meshgrid(1:N, 1:N)
>            foo(X, Y)
>        end;
>
> julia> function bench_comprehension(N)
>            [foo(x,y) for x in 1:N, y in 1:N]
>        end;
>
> # warmup omitted
>
> julia> @time bench_comprehension(1_000);
>   0.033284 seconds (6 allocations: 7.630 MB)
>
> julia> @time bench_meshgrid(1_000);
>   0.071993 seconds (70 allocations: 68.666 MB, 5.12% gc time)
>
> julia> @time bench_comprehension(10_000);
>   3.547387 seconds (6 allocations: 762.940 MB, 0.06% gc time)
>
> julia> @time bench_meshgrid(10_000);
> ERROR: OutOfMemoryError()
>  in .* at arraymath.jl:118
>  in foo at none:1
>  in bench_meshgrid at none:3
>
> Note the memory usage: for the list comprehension, it’s entirely dominated 
> by the result (10_000^2 * 8 / 1024^2 ~= 762.939 MB), while meshgrid eats 
> almost ten times as much memory (the exact ratio will vary very much 
> depending on the function foo and how many intermediate arrays it 
> creates). For large inputs, meshgrid doesn't even make it.
>
> // T
>
> On Monday, March 7, 2016 at 5:35:13 PM UTC+1, Christoph Ortner wrote:
>
> Have a look at 
>>   http://matlabcompat.github.io
>>
>> If it doesn't have a mesh grid function, then maybe mesh grid from the 
>> examples folder could be added to this package. 
>>
>> Christoph
>>
> ​
>

Reply via email to