web-dev-qa-db-fra.com

Quelle est la méthode recommandée pour itérer une matrice sur des lignes?

Étant donné une matrice m = [10i+j for i=1:3, j=1:4], Je peux parcourir ses lignes en découpant la matrice:

for i=1:size(m,1)
    print(m[i,:])
end

Est-ce la seule possibilité? Est-ce la voie recommandée?

Et qu'en est-il des compréhensions? Le découpage est-il la seule possibilité d'itérer sur les lignes d'une matrice?

[ sum(m[i,:]) for i=1:size(m,1) ]
43
Nico

La solution que vous avez répertoriée vous-même, ainsi que mapslices, fonctionnent toutes les deux correctement. Mais si par "recommandé" ce que vous entendez vraiment par "hautes performances", alors la meilleure réponse est: ne pas parcourir les lignes.

Le problème est que, puisque les tableaux sont stockés dans l'ordre des colonnes, pour tout autre chose qu'une petite matrice, vous vous retrouverez avec un mauvais taux d'accès au cache si vous parcourez le tableau dans l'ordre des lignes principales.

Comme indiqué dans un excellent article de blog , si vous voulez faire la somme des lignes, votre meilleur pari est de faire quelque chose comme ceci:

msum = zeros(eltype(m), size(m, 1))
for j = 1:size(m,2)
    for i = 1:size(m,1)
        msum[i] += m[i,j]
    end
end

Nous parcourons à la fois m et msum dans leur ordre de stockage natif, donc chaque fois que nous chargeons une ligne de cache, nous utilisons toutes les valeurs, ce qui donne un taux d'accès au cache de 1. Vous pourriez naïvement penser que c'est mieux pour le parcourir dans l'ordre des lignes principales et accumuler le résultat dans une variable tmp, mais sur toute machine moderne, le cache manquant est beaucoup plus cher que la recherche msum[i].

De nombreux algorithmes internes de Julia qui prennent un paramètre region, comme sum(m, 2), gèrent cela pour vous.

52
tholy

Depuis Julia 1.1, il existe des utilitaires d'itérateur pour itérer sur les colonnes ou les lignes d'une matrice. Pour parcourir les lignes:

M = [1 2 3; 4 5 6; 7 8 9]

for row in eachrow(af)
    println(row)
end

Sortira:

[1, 2, 3]
[4, 5, 6]
[7, 8, 9]
8
Seanny123

D'après mes expériences, les itérations explicites sont beaucoup plus rapides que les compréhensions.

Et itérer sur des colonnes est également un bon conseil.

En outre, vous pouvez utiliser les nouvelles macros @simd et @inbounds pour l'accélérer davantage.

3
Sisyphuss