This is my first post here, so I hope I can explain the problem I’ve come across as I’m writing code for my master thesis in Maths. Compared to others here I’m definitely no expert, but I trusted code from Packages to give good performance, so I’m not sure what I do wrong here or if there is in fact badly performing code in Combinatorics.permutations
I want to iterate over all permutations that keep a small vector v
(length < 6) constant so if v = [2,1,1,1]
it would be any permutation of only the last three entries. This function is called many times (for the same vector v
) within another loop, so allocations are the most important thing for me.
This is a straight forward testperm1()
equivalent to my first implementation and an dumber testperm2()
that somehow performs better
using Combinatorics
using LinearAlgebra
using BenchmarkTools
v = [2,1,1,1];
vPerm = similar(v);
n = length(v);
permArray = collect(permutations(1:n));
permMat = zeros(Int, n, n);
function testPerm1(v, n, vPerm, permMat)
for perm in permutations(1:n)
updatePermMatFromPermVec!(permMat, perm)
mul!(vPerm, permMat, v)
if vPerm == v
end
end
end
function testPerm2(v, n, vPerm, permArray, permMat)
for i in 1:factorial(n)
updatePermMatFromPermVec!(permMat, permArray[i])
mul!(vPerm, permMat, v)
if vPerm == v
end
end
end
function updatePermMatFromPermVec!(permMat, permVec)
for j in eachindex(permVec)
for i in eachindex(permVec)
if permVec[i] == j
permMat[i,j] = 1;
end
end
end
end
Again I’m not really asking for other optimizations, updatePermMatFromPermVec!
might be far from optimal, my concern is that the allocations are
@btime testPerm1(v, n, vPerm, permMat)
3.450 μs (98 allocations: 4.59 KiB)
while
@btime testPerm2(v, n, vPerm, permArray, permMat)
1.350 μs (0 allocations: 0 bytes)
and I only have to allocate permArray
once on top before hand, which gives me 1.978 μs (102 allocations: 4.91 KiB)
, so only looping over testperm1
a second time makes it a lot worse than collecting the whole array.
It seems to allocate every perm
that is iterated over, I thought using the iterator should be a lot better for performance.
I read about @inline
in another topic (I got an message saying I can’t link to it in my post), but I don’t really understand if that is also the problem here or what I can do to improve the code.
Is some dumb mistake of mine the problem or does Combinatorics
really have some bad code?