Hi all,
I want to create an array of indices (for creation of a sparse matrix in a later stage) based on a list of element connectivity as follows:
N = 10000; # Number of elements
elems = collect( [i, i+1] for i in 1:N); # List of element connectivity
I = reduce(vcat, map(e -> e[[1, 2, 1, 2]], elems));
J = reduce(vcat, map(e -> e[[1, 1, 2, 2]], elems));
For this simplified example (in reality elems
may not have this simple structure), the output should be
elems = [[1, 2], [2, 3], [3, 4], ...]
I = [1, 2, 1, 2, 2, 3, 2, 3, 3, 4, 3, 4, ...]
J = [1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, ...]
Performance of mapreduce()
The performance of the variant shown above is unexpectedly much better than that using mapreduce()
. Consider the same N
and elems
as above, then the performance I get for the two variants is
@btime begin
I = reduce(vcat, map(e -> e[[1, 2, 1, 2]], elems));
J = reduce(vcat, map(e -> e[[1, 1, 2, 2]], elems));
end
>> 1.789 ms (40014 allocations: 4.58 MiB)
Whereas with mapreduce, the time and allocated memory are much larger.
@btime begin
I = mapreduce(e -> e[[1, 2, 1, 2]], vcat, elems);
J = mapreduce(e -> e[[1, 1, 2, 2]], vcat, elems);
end
>> 25.126 ms (63644 allocations: 199.55 MiB)
The mapreduce()
documentation suggests that it should be faster than reduce(map())
because of the lack of intermediate allocation of the map. Does anyone know why this is not the case?
Further improving performance
I am fairly new to Julia, and don’t know if it would be possible to further improve the performance of this piece of code (that is, reduce its execution time and allocated memory). It is a very performance-critical part of a bigger project, so I would be grateful if you could give me some pointers.
Many thanks in advance, Gijs.