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?