2016-02-21 1 views
4

J'utilise Julia pour l'instant mais j'ai une fonction critique de performance qui nécessite une énorme quantité d'opérations matricielles répétées sur de petites matrices de taille fixe (3 dimensions ou 4 dimensions). Il semble que toutes les opérations matricielles dans Julia soient traitées par un back-end BLAS et LAPACK. Il apparaît également qu'il y a beaucoup d'allocation de mémoire dans certaines de ces fonctions.À quel point Eigen est-il plus rapide pour les petites matrices de taille fixe?

Il existe une bibliothèque julia pour small matrices qui propose des accélérations impressionnantes pour les matrices 3x3, mais n'a pas été mise à jour depuis 3 ans. Je pense réécrire ma fonction critique de performance en Eigen

Je sais que Eigen prétend être vraiment bon pour les matrices de taille fixe, mais j'essaie toujours de juger si je devrais réécrire cette fonction dans Eigen ou non. Les performances benchmarks sont pour des matrices de taille dynamique. Est-ce que quelqu'un a des données pour suggérer quelle performance on obtient des matrices de taille fixe? Les types d'opérations que je fais sont la matrice matrice x, la matrice x le vecteur, les solutions linéaires définies positives.

+0

Faites des tests de performance et voyez par vous-même. C'est la seule façon de répondre à la question avec certitude. Assurez-vous de compiler Eigen avec optimisation. Et essayez-le avec et sans OpenMP activé. – duncan

+0

Bon moment pour rappeler la citation: "Première règle d'optimisation: Ne le faites pas!", Ou les mots sages de Knuth: "L'optimisation prématurée est la racine de tout le mal.". Et sur une note positive: S'il y a un goulot d'étranglement de performance spécifique, alors partager un peu de code dans la question peut aider. –

+1

Avez-vous essayé 'Base.LinAlg.matmul3x3!' Et d'autres fonctions dans ce module? Ils contournent BLAS et permettent des calculs d'allocation minimaux. –

Répondre

3

Si vous voulez des opérations rapides pour les petites matrices, je recommande fortement FixedSizeArrays. Par exemple:

using FixedSizeArrays 

function foo(A, b, n) 
    s = 0.0 
    for i = 1:n 
     s += sum(A*b) 
    end 
    s 
end 

function foo2(A, b, n) 
    c = A*b 
    s = 0.0 
    for i = 1:n 
     A_mul_B!(c, A, b) 
     s += sum(c) 
    end 
    s 
end 

A = rand(3,3) 
b = rand(3) 
Af = Mat(A) 
bf = Vec(b) 

foo(A, b, 1) 
foo2(A, b, 1) 
foo(Af, bf, 1) 
@time 1 

@time foo(A, b, 10^6) 
@time foo2(A, b, 10^6) 
@time foo(Af, bf, 10^6) 

Résultats:

julia> include("/tmp/foo.jl") 
    0.000005 seconds (148 allocations: 10.151 KB) 
    0.325433 seconds (2.00 M allocations: 106.812 MB, 9.07% gc time) 
    0.144793 seconds (8 allocations: 304 bytes) 
    0.012683 seconds (6 allocations: 192 bytes) 

foo2 essaie d'être intelligent et d'éviter l'allocation de mémoire, mais il est tout simplement époustouflés par la mise en œuvre naïve lors de l'utilisation FixedSizeArrays.

+0

Merci pour votre réponse Tim, jusqu'ici tout va bien, il y a juste une chose qui me retient maintenant. J'ai des dizaines de milliers de 3x3 et 3x1, mais ils changent à chaque itération de mon algorithme. Idéalement, une fois qu'ils ont été créés, je voudrais les changer en utilisant setindex! c'est-à-dire bf [1] = 44, mais le paquet ne le supporte pas encore. Que devrais-je faire? – Lindon

+0

Créez-les en tant que 'Fixed 'en premier lieu. Par exemple, au lieu de retourner '[a, b, c]' à partir d'une fonction, retourner 'Vec ((a, b, c))'. Ce sera beaucoup plus rapide. Souvent, vous n'avez pas besoin de 'setindex!', Remplacez simplement la matrice entière. (Parfois, LLVM l'implémentera en tant que remplacement sous le capot, mais vous ne le saurez pas sans regarder.) – tholy

+0

J'ai un grand nombre de matrices et de vecteurs de taille fixe dans mon algorithme, qui changent à chaque itération. Pour l'instant j'ai un tableau comme x = Array {FixedSizeArrays.Vec {2, Float64}, 1}(). Si je le redimensionne alors ces types sont initialisés et l'affectation x [1] = Mat (..) ne fonctionnera plus.De même, j'ai besoin de créer ce tableau x à chaque itération de ma boucle for, et parce que c'est un grand tableau, cela représenterait une énorme charge d'allocation de mémoire. Je voudrais allouer ce tableau x avant de sauter dans ma boucle for, puis pouvoir modifier x [i]. – Lindon