NumPy配列の演算処理はなぜ速いのか
listを演算処理に使うデメリット
NumPy配列の演算処理が速い理由を知る前に、まずはlistの演算処理が遅い理由について知っておくべきであろう。
まず以下のことを把握しておく。
-
- Pythonのリストは可変長配列である
- Pythonは動的型付け言語である
Pythonのリストは、必要に応じてサイズを動的に変更することができる「可変長配列」である。リストに新たな要素が追加される場合、リストはその要素を収容するために自動的に拡大される。しかし、この操作には処理に時間とメモリ領域が必要となるため、特に大量のデータを扱う際はパフォーマンスの低下を招く。
また、Pythonのリストは異なる型の要素を含むことができるため、各要素のサイズが一定でないことがある。この特性はコーディングの手軽さに繋がる一方で、メモリ上におけるデータの効率的な配置(メモリ管理)を難しくしている。
そもそも、Pythonは動的型付け言語であり、変数の型は実行時に決定される。一方、コンパイラ言語の一部(CやJavaなど)は静的型付けが採用されており、変数の型はコンパイル時に確定(コーディング時に指定)します。Pythonは動的型付けによりフレキシブルなコーディングが可能だが、実行時に型の確認を行うためにオーバーヘッドが発生する。
その他にも以下のような点でPython言語は計算処理において不利である。
解釈実行:Pythonはソースコードを直接解釈して実行する。一方、コンパイラ言語はソースコードを事前に機械語に変換し、その結果を実行する。コンパイラが機械語への変換を行う際には処理動作の最適化ができるため、同じ処理でもコンパイラ言語の方が実行速度が速くなることが多い。
ガベージコレクション:Pythonにはガベージコレクションというメモリ管理システムが存在する。これは不要になったメモリを自動的に解放する機能であるが、この処理には時間がかかることがある。一方、Cなどの一部のコンパイラ言語では開発者が直接メモリ管理を行う必要がある。
NumPy配列(ndarray)は数値計算に特化している
numpyがPythonの組み込みリストよりも高速に動作する主な理由を挙げる。
-
-
低レベル最適化:numpyの内部はC言語で書かれており、低レベルシステムにおける最適化が可能である。これにより、Pythonの組み込みリストと比較して、大量のデータを効率的に扱うことができる。
-
連続的なメモリ配置:numpyの配列は連続したメモリ領域に配置されるが、Pythonのリストの場合その保証は無い。メモリが連続しているとCPUのキャッシュ効果を活用してデータアクセスを高速化できる。
-
ベクトル化された操作:numpyはベクトル化された操作、すなわち配列全体に対する一括の演算を可能とする。これにより各要素に対する操作を個別に行う必要が無いため、ループを明示的に書く必要が無い。これにより大規模な配列操作を高速化できる。
-
固定された型情報:numpyのndarrayは固定された型の数値しか保持できないため、配列の各要素が占めるメモリの量が不変量となる。これにより、データをメモリ上に連続的に配置できるようになり、メモリの効率的な利用が可能となる。
-