左端のインデックスが最も急速に変化する方が効率的である理由を説明するやや長い回答。理解する必要がある重要なことが2つあります。
最初に、MATLAB(およびFortran、ただしCおよびその他のほとんどのプログラミング言語ではない)は、配列を「列優先」でメモリに格納します。たとえば、Aが2 x 3 x 10の行列の場合、エントリは次の順序でメモリに保存されます
A(1,1,1)
A(2,1,1)
A(1,2,1)
A(2,2,1)
A(1,3,1)
A(2,3,1)
A(1,1,2)
A(2,1,2)
...
A(2,3,10)
列の主要な順序のこの選択は任意です。「行の主要な順序」の規則を簡単に採用できます。実際、これはCおよびその他のプログラミング言語で行われます。
理解する必要がある2番目の重要なことは、最新のプロセッサが一度に1つの場所にメモリにアクセスするのではなく、64または128の連続バイト(8または16の倍精度浮動小数点数)の「キャッシュライン」をロードして保存することです一度にメモリから。これらのデータのチャンクは一時的に高速メモリキャッシュに保存され、必要に応じて書き戻されます。(実際には、キャッシュアーキテクチャは3レベルまたは4レベルのキャッシュメモリで非常に複雑になりましたが、基本的な考え方は、若い頃にコンピューターが持っていた1レベルのキャッシュで説明できます。)
A
最も内側のループが行の添字を更新するようにループがネストされている場合、配列エントリはA(1,1)、A(2,1)、A(3,1)、...の順序でアクセスされます最初のエントリA(1,1)にアクセスすると、システムはA(1,1)、A(2,1)、...、A(8,1)を含むキャッシュラインをメインメモリからキャッシュに取り込みます。一番内側のループの次の8回の繰り返しは、追加のメインメモリ転送なしで、このデータに対して機能します。
別の方法で、最も内側のループで列インデックスが変化するようにループを構成する場合、AのエントリはA(1,1)、A(1,2)、A(1,3の順序でアクセスされます)、...この場合、最初のアクセスはA(1,1)、A(2,1)、...、A(8,1)をメインメモリからキャッシュに入れますが、これらのエントリは使用されません。2回目の反復でA(1,2)にアクセスすると、メインメモリから別の8エントリが取り込まれます。コードがマトリックスの行2で機能するようになると、A(2,1)エントリはキャッシュからフラッシュされて、他の必要なデータのための道ができます。その結果、コードは必要なトラフィックの8倍のトラフィックを生成しています。
最適化コンパイラの中には、この問題を回避するためにループを自動的に再構築できるものがあります。
行列の乗算と因数分解のための多くの数値線形代数アルゴリズムは、プログラミング言語に応じて行優先または列優先の順序スキームで効率的に動作するように最適化できます。これを間違った方法で行うと、パフォーマンスに重大な悪影響を与える可能性があります。
For
MATLABではループが非常に遅くなります。可能な限り、MATLABでの明示的なループは避けてください。代わりに、通常、問題は行列/ベクトル演算の観点から表現できます。これがMATLABの方法です。マトリックスなどを初期化するための多くの組み込み関数もあります。たとえば、マトリックスのすべての要素を1(拡張により、乗算により任意の値に設定する、ones()関数)すべて1の行列で乗算されます))。また、3次元配列でも動作します(ここで例を取り上げると思います)。