Ruleru
LLM を聞いて学ぶ

10/27(火) · 12:41

第9章 前半: 配列とメモリ、形をそろえて計算する

『日本語技術教科書 Vol.0』の第9章 前半。配列とメモリ、形をそろえて計算するを、2 人の掛け合いで解説する。

この回を聴く

AIこの記事は AI の Claude が書きました。

  • NumPy の配列は同じ型の数を詰めた領域で、型、形、歩幅が読み方を決める
  • 基本のスライスは同じ領域を覗く窓、位置を並べた指定は写し取りで、書き換えの影響が違う
  • 形の違う配列はブロードキャストで計算でき、軸は足して消す方向を指す

教材の 9.1 節から 9.2 節まで。

『日本語技術教科書 ボリュームゼロ』第9章の前半は、配列がメモリ上でどう並び、形の違う配列がどう計算されるかを扱う。

9.1.1 配列はメモリに詰めた領域

Python のリストは、整数そのものではなく、別の場所にある整数への案内札を並べた入れ物である。NumPy の配列は、同じ種類の数を一列に詰めた弁当箱のようなものにあたる。この領域を読むため、配列は型、形、1 要素あたりのバイト数という管理情報を持つ。

2 行 3 列の 32 ビット整数なら、要素は 6 個、1 個が 4 バイトなので、全体は 24 バイトになる。8 ビットの符号なし整数で 255 に 1 を足すと 0 に戻るのは、桁が一周するためで、Python の整数が桁を自動で増やすのとは別の挙動である。小さな型を選ぶほどメモリと運ぶ量は軽くなるが、整数は表せる幅が、小数は細かさが変わる。型の違う数を混ぜたときに型が自動で引き上げられる規則には、NumPy の版で変わる部分があると教材は述べている。

9.1.2 歩幅と転置

歩幅は、ある方向に添字を 1 進めたとき、メモリ上で何バイト動くかを表す。上の配列では、横に 1 つ進むと 4 バイト、縦に 1 つ進むと 12 バイトで、歩幅は 12 と 4 になる。添字に歩幅を掛けて足せば位置が求まり、2 行目の 3 つ目は 12 と 8 で 20 バイト目にある。

転置は数を並べ替えず、形と歩幅の値を入れ替えるだけで行われる。歩幅は 4 と 12 になり、数は元の場所に残る。そのため転置後に行方向へ読むと 12 バイトずつ飛ぶことになり、キャッシュの当たりやすさや、後述する行列計算ライブラリへの受け渡しの費用に響く。見かけの形が同じでも、メモリの並びまで同じとは限らない。

9.1.3 ビューとコピー

ビューは同じ領域を別の窓から眺めるもの、コピーは値を別の領域に写し取ったものを指す。基本のスライスはビューを返し、整数の並びで位置を指定する取り出し方はコピーを返す。

  • 8 個の配列から 1 つおきに取り出したビューは、歩幅が 8 バイトになる。その先頭を 99 に書き換えると、元の配列の先頭も 99 になる
  • 位置 1 と 3 を指定して取り出した結果は新しい領域なので、書き換えても元は変わらない

Python のリストのスライスは外側だけを浅く複製するため、この性質とは異なる。また、ビューが小さくても、元の大きな領域は残り続ける。窓が小さくても元の大きな領域は手放されないので、小さな部分を長く持つなら、コピーして元を解放するほうが軽くなる場面がある。形を変える操作では、今の歩幅のままでは並びを表せない場合に、値が複製される。共有の有無は、専用の関数で調べる。

9.2.1 ブロードキャスト

形の違う配列どうしを計算する決まりが、ブロードキャストである。二つの形を右端に寄せ、方向ごとに長さを見比べる。同じか、片方が 1 であれば、その方向は計算できる。先頭側に足りない方向があれば、長さ 1 とみなす。2 行 3 列に長さ 3 の並びを足すと、各行に同じ並びが足される。長さ 2 の並びでは右端が 3 と 2 で合わず、エラーになる。

各行に別の値を足したいときは、長さ 1 の方向を足して 2 行 1 列にする。長さ 1 の方向が広がるのは考え方の上だけで、実際には歩幅を 0 にして同じ場所を読み返せる。それでも答えを入れる配列は要る。10 万行 1 列と 1 行 10 万列を足すと、結果は 100 億個にもなる。倍精度の数なら、結果だけで約 800 億バイトを占める。

9.2.2〜9.2.3 ベクトル化と軸

ベクトル化は、1 個ずつ回していた計算を、配列まるごとへの一回の命令として書く考え方である。要素を取り出して計算して戻す指示を、Python 側で何度も出さずに済む。ただし、2 倍して 1 を足す式では、データを 2 回なぞる。計算は自動で 1 回の周回にはまとまらない。扱うデータが大きくなると、計算する力よりメモリの運ぶ速さが全体を左右する。

合計や平均で指定する軸は、結果に残す方向ではなく、足し合わせて消す方向である。2 行 3 列で軸 0 の合計は長さ 3、軸 1 なら長さ 2 になる。空の配列の平均は決まらず、警告つきで数でない値が返る。

9.2.4〜9.2.5 行列積と下層の実装

行列積は、左の行と右の列を組にして、対応する数を掛け、全部を足し合わせる。2 行 3 列と 3 行 2 列を掛けると 2 行 2 列になる。* で掛けると同じ位置の数どうしの積になり、行列積とは別の結果になる。計算回数の目安は、行数、列数、共通の長さを掛けた値の約 2 倍である。次元が高いときは末尾の 2 つの方向を行列とみなし、4×2×3 と 3×5 なら 4×2×5 になる。

行列積は、条件が合えば BLAS という共通の窓口を通して、つないである実装に任される。教材は実装の例として OpenBLAS、Accelerate、MKL を挙げており、どれが入っているかでスレッド数も変わる。SIMD は 1 つの命令を複数の数にまとめて当てる方式で、型や歩幅によっては使えない。100 万個の倍精度の足し算では、読む分と書く分で 24 メガバイトを動かす。毎秒 24 ギガバイトで運べると仮定すると、運ぶだけで約 1000 分の 1 秒かかる。教材はこれを説明用の概算とし、実際の速さの保証ではないとしている。

次の後半では、桁に限りのある小数の扱いと、ニューラルネットの計算を取り上げる。

出典

  • オーナー(AI で作った教材、Web には公開していない) 日本語技術教科書 Vol.0 コンピュータからPython・機械学習・LLMへ 第9章 2026-10-18