Julia: sum|mapreduce versus boucle for déroulée. disparité des performances

Créé le 8 févr. 2017  ·  3Commentaires  ·  Source: JuliaLang/julia

mapreduce peut être beaucoup plus lent que la boucle for équivalente. Un petit exemple ( réel ) :

function dsum(A::Matrix)
    z = zero(A[1,1])
    n = Base.LinAlg.checksquare(A)
    B = Vector{typeof(z)}(n)

    <strong i="9">@inbounds</strong> for j in 1:n
        B[j] = mapreduce(k -> A[j,k]*A[k,j], +, z, 1:j)
    end
    B
end
function dfor(A::Matrix)
    z = zero(A[1,1])
    n = Base.LinAlg.checksquare(A)
    B = Vector{typeof(z)}(n)

    <strong i="10">@inbounds</strong> for j in 1:n
        d = z
        for k in 1:j
            d += A[j,k]*A[k,j]
        end
        B[j] = d
    end
    B
end

A = randn(127,127)
time(median(<strong i="11">@benchmark</strong> dsum(A)))/time(median(<strong i="12">@benchmark</strong> dfor(A)))

me donne un ratio de performance d'environ x50 sur Julia 0.5, juliabox.com. Je pense que cela pourrait être dû au fait que la boucle for peut être automatiquement simd , et que mapreduce ne l'est pas? Lorsque A = randn(N,N) et N est 16 , l'écart est d'environ x75, et pour N = 10000 , l'écart est d'environ x25. Remplacer l'accès au tableau A[j,k] par A[rand(1:size(A,1)),rand(1:size(A,2))] détruit les performances des deux, mais le ratio devient x1.

  1. Est-ce simd est la raison pour laquelle on est x50 plus rapide ?
  2. Cela devrait-il être décrit dans les conseils de performance ? mapreduce sous-tend sum , donc cela pourrait être un piège populaire qui n'est pas mentionné actuellement
  3. Serait-ce un repère utile ? sur nanosoldat ?
  4. L'écart de performance pourrait-il être moindre ?

(Benchmarking mapreduce contre for -boucles sans accès au tableau, je vois toujours un écart de performance x2. Par exemple, mapreduce(identity, +, 0, i for i in 1:n) par rapport à la boucle équivalente de somme entière for . Il semble que cet écart était plus petit ? Vaut-il une autre référence en CI ?)

performance

Commentaire le plus utile

+1 pour avoir mis une référence de cela dans BaseBenchmarks ; un PR il serait super.

Tous les 3 commentaires

Ressemble à une copie de https://github.com/JuliaLang/julia/issues/15276.

En faisant:

function dsum(A::Matrix)
    z = zero(A[1,1])
    n = Base.LinAlg.checksquare(A)
    B = Vector{typeof(z)}(n)
    <strong i="8">@inbounds</strong> for j::Int in 1:n
        B[j] = _help(A, j, z)
    end
    B
end

_help(A, j, z) = mapreduce(k -> A[j,k]*A[k,j], +, z, 1:j)

donne

julia> time(median(<strong i="12">@benchmark</strong> dsum(A)))/time(median(<strong i="13">@benchmark</strong> dfor(A)))
1.0013213312412255

Vous pouvez voir le problème en @code_warntype et en recherchant Core.Box .

+1 pour avoir mis une référence de cela dans BaseBenchmarks ; un PR il serait super.

Clôture en double du #15276.

Cette page vous a été utile?
0 / 5 - 0 notes

Questions connexes

StefanKarpinski picture StefanKarpinski  ·  3Commentaires

tkoolen picture tkoolen  ·  3Commentaires

omus picture omus  ·  3Commentaires

iamed2 picture iamed2  ·  3Commentaires

ararslan picture ararslan  ·  3Commentaires