与えられた行列m = [10i+j for i=1:3, j=1:4]
、行列をスライスすることで行を反復できます。
for i=1:size(m,1)
print(m[i,:])
end
これが唯一の可能性ですか?お勧めの方法ですか?
そして、理解はどうですか?スライスすることは、行列の行を反復する唯一の可能性ですか?
[ sum(m[i,:]) for i=1:size(m,1) ]
自分でリストしたソリューションとmapslices
はどちらも正常に機能します。しかし、「推奨」が本当に意味するのが「高性能」である場合、最善の答えは、行を反復しないことです。
問題は、配列が列優先で格納されているため、小さな行列以外の場合は、行優先で配列をトラバースすると キャッシュヒット率 になってしまうことです。
優れたブログ投稿 で指摘されているように、行を合計したい場合、最善の策は次のようなことです。
_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
_
ネイティブストレージ順でm
とmsum
の両方をトラバースするため、キャッシュラインをロードするたびにすべての値を使用し、キャッシュヒット率を1にします。行優先順でトラバースして結果をtmp
変数に累積しますが、最近のマシンでは、キャッシュミスは_msum[i]
_ルックアップよりもはるかにコストがかかります。
sum(m, 2)
のようなregion
パラメータを取るJuliaの内部アルゴリズムの多くは、これを処理します。
Julia 1.1以降、行列の列または行を反復するための反復ユーティリティがあります。行を反復するには:
M = [1 2 3; 4 5 6; 7 8 9]
for row in eachrow(af)
println(row)
end
出力されます:
[1, 2, 3]
[4, 5, 6]
[7, 8, 9]
私の経験によれば、明示的な反復は内包よりもはるかに高速です。
また、列を反復処理することも良いアドバイスです。
さらに、新しいマクロ@simdおよび@inboundsを使用して、さらに高速化できます。