Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

using MutableArithmetic makes DynamicPolynomials slower? #64

Open
kalmarek opened this issue Jul 17, 2020 · 4 comments
Open

using MutableArithmetic makes DynamicPolynomials slower? #64

kalmarek opened this issue Jul 17, 2020 · 4 comments

Comments

@kalmarek
Copy link

kalmarek commented Jul 17, 2020

Setup: (mt is a multiplication table of an algebra)

using DynamicPolynomials
using MutableArithmetics

@inline function algebra_addmul!(
        res::AbstractVector,
        X::AbstractVector,
        Y::AbstractVector,
        mt::AbstractMatrix{<:Integer})
    
    @inbounds for j in 1:size(mt,2)
        for i in 1:size(mt,1)
            res[mt[i,j]] = MutableArithmetics.add_mul!(res[mt[i,j]], X[i], Y[j])
#             res[mt[i,j]] += X[i]*X[j] 
        end
    end
    return res
end

function algebra_SOS(Q::AbstractMatrix{T}, mt::AbstractMatrix{<:Integer}) where T
#     result = zeros(T, maximum(mt)) doesn't work
    result = fill(zero(T), maximum(mt))
    for i in 1:size(Q,2)
        @views algebra_addmul!(result, Q[:,i], Q[:,i], mt)
    end
end

and timings (on contrived example):

using Random

let N = 13
    Random.seed!(1)
    @polyvar V[1:N^2]
    mt = rand(1:N^2, N, N)
    Q = V[rand(1:N^2, N, N)]
    
    algebra_SOS(Q, mt)
    m = rand(N,N)
    algebra_SOS(m, mt)
    
    @time algebra_SOS(Q, mt)
    @time algebra_SOS(m, mt)
end;
# with res[mt[i,j]] = MutableArithmetics.add_mul!(res[mt[i,j]], X[i], Y[j])
  0.261018 seconds (833.87 k allocations: 47.396 MiB)
  0.000004 seconds (1 allocation: 1.453 KiB)

# with res[mt[i,j]] += X[i]*X[j] 
0.015759 seconds (120.20 k allocations: 15.800 MiB)
  0.000008 seconds (1 allocation: 1.453 KiB)

@blegat, @tweisser

@blegat
Copy link
Member

blegat commented Jul 17, 2020

This is weird, MA should be much faster for this with less allocations. Does the issue persist if mt[i, j] is replaced by i + (j - 1) * N ? EDIT it seems it does persist

@blegat
Copy link
Member

blegat commented Jul 17, 2020

#65 solves one part of the performance issue but it's still slower.

@blegat
Copy link
Member

blegat commented Jul 20, 2020

The issue is that fill(zero(T), maximum(mt)) uses the same polynomial for every entry so it's slower because it modifies a large polynomial. You should use [zero(T) for i in 1:maximum(mt)] for instance

@kalmarek
Copy link
Author

@blegat thanks for investigating; interesting find: indeed v = fill(zero(T), 3) results in identical (===) entries, but modifying one unaliases it from the others (?). When using

function algebra_SOS(Q::AbstractMatrix{T}, mt::AbstractMatrix{<:Integer}) where T
#     result = zeros(T, maximum(mt)) doesn't work
    result = [zero(T) for _ in 1:maximum(mt)]
    for i in 1:size(Q,2)
        @views algebra_addmul!(result, Q[:,i], Q[:,i], mt)
    end
end

I get the following timings:

0.026193 seconds (235.44 k allocations: 30.099 MiB, 17.03% gc time) # with add_mul!
0.015501 seconds (121.20 k allocations: 15.861 MiB) # with res[mt[i,j]] += X[i]*X[j] 

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants