ベクトル化

ベクトル化

執筆済 科学計算

要素ごとのループを、配列全体の演算として書き直す。

python
# ループ — 遅い
result = []
for x in data:
    result.append(x * 2 + 1)

# ベクトル化 — 速い
result = data * 2 + 1

なぜ速いのか#

Python のループでは、1 要素ごとに

  1. バイトコードのディスパッチ
  2. オブジェクトの型判定
  3. メソッド呼び出し
  4. 結果オブジェクトの確保

が起きる。計算そのものより付随処理が支配的

ベクトル化すると、これらが 1 回で済み、 実際のループは C の中で回る。 さらに SIMD も効く。

10〜100 倍の差がつくのが普通。

代償#

代償 内容
メモリ 中間結果の配列が確保される
可読性 複雑な条件分岐は書きにくい
早期終了できない 条件を満たしたら止める、が書けない
python
a * 2 + b * 3 + c   # 中間配列が 3 つできる

巨大配列ではメモリが問題になる。 np.add(a, b, out=a) のような in-place 演算や、 NumExpr、Numba で融合させる手がある。

ベクトル化しにくいもの#

  • 前の反復の結果に依存する(漸化式)
  • 要素ごとに違う分岐をする
  • 可変長の処理

こうした場合は Numba(JIT)、Cython、 あるいは C 拡張に降りる。

より広い意味#

「ベクトル化」は CPU の SIMD 命令を指すこともある。 NumPy の意味では **「ループを高速な実装に委ねる」**という より抽象的な原則を指す。

深層学習でバッチ処理をするのも、 GPU に 大きな行列演算として渡すためで、同じ発想。

参考文献#

ノート一覧を閉じる