目次へのリンク
概要
MATLABプログラムを高速する2つのTipsを紹介します。
- 配列の事前割当:必要なサイズの配列を事前に確保し、メモリ再配置による性能低下を防ぎます。
- ベクトル化:ループ処理を行列ベクトル操作に書き換えることで高速に実行できます。
対応ファイル:I1_04_2_Speed_Up.m
配列の事前割り当てなし(低速)
ループの中で変数xの要素の数がだんだん大きくなります。配列サイズが変更される際に、メモリの再配置など起き、実行速度を低下させます。
clear
tic
for n = 1:1e7
x(n) = n;
end
toc
経過時間は 1.263031 秒です。
配列の事前割り当て(高速)
事前に配列を割り当てておくことでメモリ管理のオーバーヘッドを減らし、高速化が期待できます。
clear
x = zeros(1e7,1); % 事前に配列割当
tic
for n = 1:1e7
x(n) = n;
end
toc
経過時間は 0.068325 秒です。
要素をスキャンする:横方向 (低速)
4000x4000の行列の、要素が0.5以上の場所をtrue
にします。
行列および配列はメモリ上に連続して配置されています。
MATLABの配列データは列優先の順序で格納されています。
横方向(行方向)に連続アクセスしても、実際のメモリの配置は飛び飛びになっており、読み書きの性能が低下します。
clear
X = rand(4000);
Y = false(4000);
tic
for r = 1:4000 % 行
for c = 1:4000 % 列
if X(r, c) > 0.5
Y(r, c) = true;
end
end
end
toc
経過時間は 0.375143 秒です。
縦方向に要素をスキャンする(速い)
縦方向(列方向)に連続アクセスすることで、メモリ上のデータの配置も連続となり、読み書きが高速化されます。
clear
X = rand(4000);
Y = false(4000);
tic
for c = 1:4000 % 列
for r = 1:4000 % 行
if X(r, c) > 0.5
Y(r, c) = true;
end
end
end
toc
経過時間は 0.193692 秒です。
配列として処理 (ベクトル化、より高速)
MATLABの演算子や関数はベクトルや行列を引数として取ることができます。
比較演算子も行列に直接適用が可能です。
ループベースの処理を行列やベクトル操作に変更することを"ベクトル化"と呼びます。
多くの場合、ベクトル化はループベースの処理と比較して高速です。
可読性も向上し、エラーも減るため、積極的に活用しましょう。
clear
X = rand(4000);
Y = false(4000);
tic
Y = X > 0.5;
toc
経過時間は 0.023169 秒です。
まとめ
MATLABプログラムの高速化について配列の事前割当とベクトル化について紹介しました。
配列の事前割当は速度をかなり改善できる可能性があります。
ベクトル化については高速化のみならず、可読性や不具合の混入リスクを下げることにもつながります。
MATLABプログラムのパフォーマンス向上にお役立てください。
参考
謝辞
本記事は @eigs さんのlivescript2markdownを使わせていただいてます。