<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Latent State // ログ</title><description>機械学習・GPU計算・Kaggleコンペについての技術エッセイ。</description><link>https://latentstate.dev/ja/</link><language>ja</language><item><title>行列積 — 定義からキャッシュラインまで</title><link>https://latentstate.dev/ja/posts/matrix-multiplication/</link><guid isPermaLink="true">https://latentstate.dev/ja/posts/matrix-multiplication/</guid><description>同じ乗算を3通りに実装すると3桁の差がつく。Skylake デスクトップでの実測をもとに、キャッシュライン・演算強度・タイリングという、あらゆる BLAS と GPU 行列積カーネルを支える考え方を解説する。</description><pubDate>Tue, 28 Jul 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;私がこれまで本番投入してきたモデル — トランスフォーマーの各層も、value ヘッドも、音声エンコーダも — その FLOP の大半をたったひとつの演算の中で使っている。&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo&gt;∈&lt;/mo&gt;&lt;msup&gt;&lt;mi mathvariant=&quot;double-struck&quot;&gt;R&lt;/mi&gt;&lt;mrow&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mi&gt;k&lt;/mi&gt;&lt;/mrow&gt;&lt;/msup&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;A \in \R^{m \times k}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;/span&gt;、&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;mo&gt;∈&lt;/mo&gt;&lt;msup&gt;&lt;mi mathvariant=&quot;double-struck&quot;&gt;R&lt;/mi&gt;&lt;mrow&gt;&lt;mi&gt;k&lt;/mi&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;/mrow&gt;&lt;/msup&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;B \in \R^{k \times n}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;/span&gt; に対し、積 &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;C = AB&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;/span&gt; は成分ごとに次のように定義される:&lt;/p&gt;
&lt;span class=&quot;katex-display&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot; display=&quot;block&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msub&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mrow&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;j&lt;/mi&gt;&lt;/mrow&gt;&lt;/msub&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;munderover&gt;&lt;mo&gt;∑&lt;/mo&gt;&lt;mrow&gt;&lt;mi&gt;p&lt;/mi&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;/mrow&gt;&lt;mi&gt;k&lt;/mi&gt;&lt;/munderover&gt;&lt;msub&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mrow&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;p&lt;/mi&gt;&lt;/mrow&gt;&lt;/msub&gt;&lt;mtext&gt; &lt;/mtext&gt;&lt;msub&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mrow&gt;&lt;mi&gt;p&lt;/mi&gt;&lt;mi&gt;j&lt;/mi&gt;&lt;/mrow&gt;&lt;/msub&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mspace width=&quot;2em&quot;&gt;&lt;/mspace&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;mo&gt;≤&lt;/mo&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mo&gt;≤&lt;/mo&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mtext&gt; &lt;/mtext&gt;&lt;mtext&gt;  &lt;/mtext&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;mo&gt;≤&lt;/mo&gt;&lt;mi&gt;j&lt;/mi&gt;&lt;mo&gt;≤&lt;/mo&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;.&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;c_{ij} = \sum_{p=1}^{k} a_{ip}\, b_{pj},
\qquad 1 \le i \le m,\ \; 1 \le j \le n.&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;これは &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mi&gt;k&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;mnk&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;/span&gt; 回の積和 — &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mi&gt;k&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;2mnk&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;/span&gt; FLOP — であり、定義はそのまま誰もが最初に書く行列積のコードになる。定義は3重ループにすぎない。性能はメモリの物語であり、この記事はそれをキャッシュラインまで掘り下げる。&lt;/p&gt;
&lt;h2 id=&quot;2億6800万flopの使い方3通り&quot;&gt;2億6800万FLOPの使い方、3通り&lt;/h2&gt;
&lt;p&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mi&gt;k&lt;/mi&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mn&gt;512&lt;/mn&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;m = n = k = 512&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;/span&gt; のとき、積のコストは &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;mo&gt;⋅&lt;/mo&gt;&lt;msup&gt;&lt;mn&gt;512&lt;/mn&gt;&lt;mn&gt;3&lt;/mn&gt;&lt;/msup&gt;&lt;mo&gt;≈&lt;/mo&gt;&lt;mn&gt;2.7&lt;/mn&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;msup&gt;&lt;mn&gt;10&lt;/mn&gt;&lt;mn&gt;8&lt;/mn&gt;&lt;/msup&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;2 \cdot 512^3 \approx 2.7 \times 10^8&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;/span&gt; FLOP。以下が定義そのままのコードで、&lt;a href=&quot;/code/matmul_bench.py&quot;&gt;ベンチマークスクリプト&lt;/a&gt;が計測しているのはまさにこの関数である:&lt;/p&gt;
&lt;pre class=&quot;astro-code astro-code-themes vitesse-light vitesse-dark&quot; style=&quot;--shiki-light:#393a34;--shiki-dark:#dbd7caee;--shiki-light-bg:#ffffff;--shiki-dark-bg:#121212; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;python&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#AB5959;--shiki-dark:#CB7676&quot;&gt;def&lt;/span&gt;&lt;span style=&quot;--shiki-light:#59873A;--shiki-dark:#80A665&quot;&gt; matmul_naive&lt;/span&gt;&lt;span style=&quot;--shiki-light:#999999;--shiki-dark:#666666&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--shiki-light:#393A34;--shiki-dark:#DBD7CAEE&quot;&gt;A&lt;/span&gt;&lt;span style=&quot;--shiki-light:#999999;--shiki-dark:#666666&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--shiki-light:#393A34;--shiki-dark:#DBD7CAEE&quot;&gt; B&lt;/span&gt;&lt;span style=&quot;--shiki-light:#999999;--shiki-dark:#666666&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--shiki-light:#393A34;--shiki-dark:#DBD7CAEE&quot;&gt; n&lt;/span&gt;&lt;span style=&quot;--shiki-light:#999999;--shiki-dark:#666666&quot;&gt;):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#393A34;--shiki-dark:#DBD7CAEE&quot;&gt;    C &lt;/span&gt;&lt;span style=&quot;--shiki-light:#999999;--shiki-dark:#666666&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--shiki-light:#999999;--shiki-dark:#666666&quot;&gt; [[&lt;/span&gt;&lt;span style=&quot;--shiki-light:#2F798A;--shiki-dark:#4C9A91&quot;&gt;0.0&lt;/span&gt;&lt;span style=&quot;--shiki-light:#999999;--shiki-dark:#666666&quot;&gt;]&lt;/span&gt;&lt;span style=&quot;--shiki-light:#AB5959;--shiki-dark:#CB7676&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;--shiki-light:#393A34;--shiki-dark:#DBD7CAEE&quot;&gt; n &lt;/span&gt;&lt;span style=&quot;--shiki-light:#1E754F;--shiki-dark:#4D9375&quot;&gt;for&lt;/span&gt;&lt;span style=&quot;--shiki-light:#393A34;--shiki-dark:#DBD7CAEE&quot;&gt; _ &lt;/span&gt;&lt;span style=&quot;--shiki-light:#1E754F;--shiki-dark:#4D9375&quot;&gt;in&lt;/span&gt;&lt;span style=&quot;--shiki-light:#998418;--shiki-dark:#B8A965&quot;&gt; range&lt;/span&gt;&lt;span style=&quot;--shiki-light:#999999;--shiki-dark:#666666&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--shiki-light:#393A34;--shiki-dark:#DBD7CAEE&quot;&gt;n&lt;/span&gt;&lt;span style=&quot;--shiki-light:#999999;--shiki-dark:#666666&quot;&gt;)]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#1E754F;--shiki-dark:#4D9375&quot;&gt;    for&lt;/span&gt;&lt;span style=&quot;--shiki-light:#393A34;--shiki-dark:#DBD7CAEE&quot;&gt; i &lt;/span&gt;&lt;span style=&quot;--shiki-light:#1E754F;--shiki-dark:#4D9375&quot;&gt;in&lt;/span&gt;&lt;span style=&quot;--shiki-light:#998418;--shiki-dark:#B8A965&quot;&gt; range&lt;/span&gt;&lt;span style=&quot;--shiki-light:#999999;--shiki-dark:#666666&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--shiki-light:#393A34;--shiki-dark:#DBD7CAEE&quot;&gt;n&lt;/span&gt;&lt;span style=&quot;--shiki-light:#999999;--shiki-dark:#666666&quot;&gt;):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#1E754F;--shiki-dark:#4D9375&quot;&gt;        for&lt;/span&gt;&lt;span style=&quot;--shiki-light:#393A34;--shiki-dark:#DBD7CAEE&quot;&gt; j &lt;/span&gt;&lt;span style=&quot;--shiki-light:#1E754F;--shiki-dark:#4D9375&quot;&gt;in&lt;/span&gt;&lt;span style=&quot;--shiki-light:#998418;--shiki-dark:#B8A965&quot;&gt; range&lt;/span&gt;&lt;span style=&quot;--shiki-light:#999999;--shiki-dark:#666666&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--shiki-light:#393A34;--shiki-dark:#DBD7CAEE&quot;&gt;n&lt;/span&gt;&lt;span style=&quot;--shiki-light:#999999;--shiki-dark:#666666&quot;&gt;):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#393A34;--shiki-dark:#DBD7CAEE&quot;&gt;            acc &lt;/span&gt;&lt;span style=&quot;--shiki-light:#999999;--shiki-dark:#666666&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--shiki-light:#2F798A;--shiki-dark:#4C9A91&quot;&gt; 0.0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#1E754F;--shiki-dark:#4D9375&quot;&gt;            for&lt;/span&gt;&lt;span style=&quot;--shiki-light:#393A34;--shiki-dark:#DBD7CAEE&quot;&gt; p &lt;/span&gt;&lt;span style=&quot;--shiki-light:#1E754F;--shiki-dark:#4D9375&quot;&gt;in&lt;/span&gt;&lt;span style=&quot;--shiki-light:#998418;--shiki-dark:#B8A965&quot;&gt; range&lt;/span&gt;&lt;span style=&quot;--shiki-light:#999999;--shiki-dark:#666666&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--shiki-light:#393A34;--shiki-dark:#DBD7CAEE&quot;&gt;n&lt;/span&gt;&lt;span style=&quot;--shiki-light:#999999;--shiki-dark:#666666&quot;&gt;):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#393A34;--shiki-dark:#DBD7CAEE&quot;&gt;                acc &lt;/span&gt;&lt;span style=&quot;--shiki-light:#999999;--shiki-dark:#666666&quot;&gt;+=&lt;/span&gt;&lt;span style=&quot;--shiki-light:#393A34;--shiki-dark:#DBD7CAEE&quot;&gt; A&lt;/span&gt;&lt;span style=&quot;--shiki-light:#999999;--shiki-dark:#666666&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;--shiki-light:#393A34;--shiki-dark:#DBD7CAEE&quot;&gt;i&lt;/span&gt;&lt;span style=&quot;--shiki-light:#999999;--shiki-dark:#666666&quot;&gt;][&lt;/span&gt;&lt;span style=&quot;--shiki-light:#393A34;--shiki-dark:#DBD7CAEE&quot;&gt;p&lt;/span&gt;&lt;span style=&quot;--shiki-light:#999999;--shiki-dark:#666666&quot;&gt;]&lt;/span&gt;&lt;span style=&quot;--shiki-light:#AB5959;--shiki-dark:#CB7676&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;--shiki-light:#393A34;--shiki-dark:#DBD7CAEE&quot;&gt; B&lt;/span&gt;&lt;span style=&quot;--shiki-light:#999999;--shiki-dark:#666666&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;--shiki-light:#393A34;--shiki-dark:#DBD7CAEE&quot;&gt;p&lt;/span&gt;&lt;span style=&quot;--shiki-light:#999999;--shiki-dark:#666666&quot;&gt;][&lt;/span&gt;&lt;span style=&quot;--shiki-light:#393A34;--shiki-dark:#DBD7CAEE&quot;&gt;j&lt;/span&gt;&lt;span style=&quot;--shiki-light:#999999;--shiki-dark:#666666&quot;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#393A34;--shiki-dark:#DBD7CAEE&quot;&gt;            C&lt;/span&gt;&lt;span style=&quot;--shiki-light:#999999;--shiki-dark:#666666&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;--shiki-light:#393A34;--shiki-dark:#DBD7CAEE&quot;&gt;i&lt;/span&gt;&lt;span style=&quot;--shiki-light:#999999;--shiki-dark:#666666&quot;&gt;][&lt;/span&gt;&lt;span style=&quot;--shiki-light:#393A34;--shiki-dark:#DBD7CAEE&quot;&gt;j&lt;/span&gt;&lt;span style=&quot;--shiki-light:#999999;--shiki-dark:#666666&quot;&gt;]&lt;/span&gt;&lt;span style=&quot;--shiki-light:#999999;--shiki-dark:#666666&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;--shiki-light:#393A34;--shiki-dark:#DBD7CAEE&quot;&gt; acc&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#1E754F;--shiki-dark:#4D9375&quot;&gt;    return&lt;/span&gt;&lt;span style=&quot;--shiki-light:#393A34;--shiki-dark:#DBD7CAEE&quot;&gt; C&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;私のデスクトップでは、Python のリスト上でこれが &lt;strong&gt;9.3秒&lt;/strong&gt; かかる。一見「最適化」に見える書き換え — 同じ3重ループを NumPy 配列のスカラー添字 (&lt;code&gt;A[i, p] * B[p, j]&lt;/code&gt;) で回す — は &lt;strong&gt;41.9秒&lt;/strong&gt;、素のリストの4.5倍も遅い。そして OpenBLAS に委譲される &lt;code&gt;A @ B&lt;/code&gt; は、1スレッドで &lt;strong&gt;5.1ミリ秒&lt;/strong&gt;。同じ行列、同じ2億6800万FLOP、答えは &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mn&gt;2.3&lt;/mn&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;msup&gt;&lt;mn&gt;10&lt;/mn&gt;&lt;mrow&gt;&lt;mo&gt;−&lt;/mo&gt;&lt;mn&gt;13&lt;/mn&gt;&lt;/mrow&gt;&lt;/msup&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;2.3 \times 10^{-13}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;/span&gt; の精度で一致する:&lt;/p&gt;
&lt;figure class=&quot;fig-light&quot;&gt;&lt;a href=&quot;https://latentstate.dev/ja/posts/matrix-multiplication/&quot;&gt;[図 — サイトで見る]&lt;/a&gt;&lt;figcaption&gt;図1 — 同じ乗算、3通りの実装。対数スケールに注意&lt;/figcaption&gt;&lt;/figure&gt;

&lt;p&gt;このグラフには説明すべき点がふたつある。スキャンダルのほう — NumPy が素のリストに4.5倍負ける — の種明かしは簡単だ。&lt;code&gt;A[i, p]&lt;/code&gt; のたびに C-API の境界を越えて Python の float オブジェクトをひとつ箱詰めする。1アクセスあたり約 120ナノ秒のオーバーヘッドが、2億6800万回。NumPy の契約は&lt;em&gt;配列まるごと&lt;/em&gt;の演算であり、リストのように添字で触れば、機構の代金だけ払って機構を一度も使わないことになる。&lt;/p&gt;
&lt;p&gt;興味深いのはもうひとつの数字だ。愚直なループと &lt;code&gt;A @ B&lt;/code&gt; の間の &lt;strong&gt;1800倍&lt;/strong&gt; — OpenBLAS は定義が要求する &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mi&gt;k&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;2mnk&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;/span&gt; FLOP を、同じ倍精度で、過不足なく実行している。このうちインタープリタの寄与はせいぜい2桁分 — 同じ3重ループを &lt;code&gt;-O3&lt;/code&gt; でコンパイルすれば、このクラスのコアではだいたい1〜2 GFLOP/s になる。残り、コンパイルしても消えない30倍余りの因子 — それが&lt;em&gt;メモリ&lt;/em&gt;である。&lt;/p&gt;
&lt;details&gt;
&lt;summary&gt;ベンチマーク環境&lt;/summary&gt;
&lt;p&gt;Intel i7-6700K(Skylake、4コア/8スレッド、ベース4.0 GHz/シングルコアターボ4.2 GHz)、キャッシュはコアあたり L1d 32 KB + L2 256 KB、共有 L3 8 MB、デュアルチャネル DDR4。Python 3.11.7、NumPy 2.4.2(scipy-openblas)、すべて float64。BLAS は &lt;code&gt;OPENBLAS_NUM_THREADS=1&lt;/code&gt; で1スレッドに固定(末尾のマルチスレッド計測を除く)。遅い2つのループは1回実行、それ以外は固定シードでベスト・オブ・5。結果は &lt;code&gt;A @ B&lt;/code&gt; と照合済み: 最大絶対偏差 ≈ 2.3 × 10⁻¹³。&lt;/p&gt;
&lt;/details&gt;
&lt;h2 id=&quot;64バイトの真実&quot;&gt;64バイトの真実&lt;/h2&gt;
&lt;p&gt;CPU がメモリから &lt;code&gt;float64&lt;/code&gt; を1個だけ読むことはない。読むのは&lt;strong&gt;キャッシュライン&lt;/strong&gt; — 64バイト、double 8個 — であり、それをキャッシュ階層に保持する。このマシンではコアあたり L1d 32 KB、L2 256 KB、全コア共有の L3 8 MB。L1 ヒットのロードは約4サイクル、DRAM までの往復は数百サイクル。速い数値計算コードのすべては、ひとつの規則から導かれる: &lt;em&gt;ラインを引いてきたら、そこに載っているものを使い切れ — そして追い出される前に再利用しろ。&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;NumPy は行列を行優先(C順)で格納する。行 &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;i&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;/span&gt; は連続で、要素 &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msub&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mrow&gt;&lt;mi&gt;p&lt;/mi&gt;&lt;mi&gt;j&lt;/mi&gt;&lt;/mrow&gt;&lt;/msub&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;b_{pj}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;/span&gt; は &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msub&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mrow&gt;&lt;mi&gt;p&lt;/mi&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi&gt;j&lt;/mi&gt;&lt;mo&gt;−&lt;/mo&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;/mrow&gt;&lt;/msub&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;b_{p,j-1}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;/span&gt; の8バイト先にあるが、&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msub&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mrow&gt;&lt;mi&gt;p&lt;/mi&gt;&lt;mo&gt;−&lt;/mo&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi&gt;j&lt;/mi&gt;&lt;/mrow&gt;&lt;/msub&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;b_{p-1,j}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;/span&gt; からは行1本ぶん先にある。ここで定義の内側ループを見てほしい。&lt;code&gt;A[i][p]&lt;/code&gt; は行に&lt;em&gt;沿って&lt;/em&gt;進む — 逐次アクセスで、フェッチしたライン1本につき8個の double が全部役に立ち、ハードウェアプリフェッチャが得意とするパターンで先回りしてくれる。一方 &lt;code&gt;B[p][j]&lt;/code&gt; は列を&lt;em&gt;下へ&lt;/em&gt;、1ステップごとに4 KB ずつ跳ぶ。この下降は毎ステップ新しいキャッシュラインと新しいメモリページを開く。列を1本下りきるだけで512本の異なるライン(4 KB の有効データのために32 KB のトラフィック)に触れ、プリフェッチャには取り付く島もない。&lt;/p&gt;
&lt;p&gt;この効果は行列積なしでも簡単に分離できる。8192×8192 の行列1枚 — 537 MB、どのキャッシュよりはるかに大きい — を、行沿いと列沿いで2回合計してみる:&lt;/p&gt;
&lt;pre class=&quot;astro-code astro-code-themes vitesse-light vitesse-dark&quot; style=&quot;--shiki-light:#393a34;--shiki-dark:#dbd7caee;--shiki-light-bg:#ffffff;--shiki-dark-bg:#121212; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;python&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#393A34;--shiki-dark:#DBD7CAEE&quot;&gt;M &lt;/span&gt;&lt;span style=&quot;--shiki-light:#999999;--shiki-dark:#666666&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--shiki-light:#393A34;--shiki-dark:#DBD7CAEE&quot;&gt; rng&lt;/span&gt;&lt;span style=&quot;--shiki-light:#999999;--shiki-dark:#666666&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--shiki-light:#393A34;--shiki-dark:#DBD7CAEE&quot;&gt;standard_normal&lt;/span&gt;&lt;span style=&quot;--shiki-light:#999999;--shiki-dark:#666666&quot;&gt;((&lt;/span&gt;&lt;span style=&quot;--shiki-light:#2F798A;--shiki-dark:#4C9A91&quot;&gt;8192&lt;/span&gt;&lt;span style=&quot;--shiki-light:#999999;--shiki-dark:#666666&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--shiki-light:#2F798A;--shiki-dark:#4C9A91&quot;&gt; 8192&lt;/span&gt;&lt;span style=&quot;--shiki-light:#999999;--shiki-dark:#666666&quot;&gt;))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#393A34;--shiki-dark:#DBD7CAEE&quot;&gt;s &lt;/span&gt;&lt;span style=&quot;--shiki-light:#999999;--shiki-dark:#666666&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--shiki-light:#2F798A;--shiki-dark:#4C9A91&quot;&gt; 0.0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#1E754F;--shiki-dark:#4D9375&quot;&gt;for&lt;/span&gt;&lt;span style=&quot;--shiki-light:#393A34;--shiki-dark:#DBD7CAEE&quot;&gt; i &lt;/span&gt;&lt;span style=&quot;--shiki-light:#1E754F;--shiki-dark:#4D9375&quot;&gt;in&lt;/span&gt;&lt;span style=&quot;--shiki-light:#998418;--shiki-dark:#B8A965&quot;&gt; range&lt;/span&gt;&lt;span style=&quot;--shiki-light:#999999;--shiki-dark:#666666&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--shiki-light:#2F798A;--shiki-dark:#4C9A91&quot;&gt;8192&lt;/span&gt;&lt;span style=&quot;--shiki-light:#999999;--shiki-dark:#666666&quot;&gt;):&lt;/span&gt;&lt;span style=&quot;--shiki-light:#393A34;--shiki-dark:#DBD7CAEE&quot;&gt; s &lt;/span&gt;&lt;span style=&quot;--shiki-light:#999999;--shiki-dark:#666666&quot;&gt;+=&lt;/span&gt;&lt;span style=&quot;--shiki-light:#393A34;--shiki-dark:#DBD7CAEE&quot;&gt; M&lt;/span&gt;&lt;span style=&quot;--shiki-light:#999999;--shiki-dark:#666666&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;--shiki-light:#393A34;--shiki-dark:#DBD7CAEE&quot;&gt;i&lt;/span&gt;&lt;span style=&quot;--shiki-light:#999999;--shiki-dark:#666666&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--shiki-light:#999999;--shiki-dark:#666666&quot;&gt; :].&lt;/span&gt;&lt;span style=&quot;--shiki-light:#393A34;--shiki-dark:#DBD7CAEE&quot;&gt;sum&lt;/span&gt;&lt;span style=&quot;--shiki-light:#999999;--shiki-dark:#666666&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;--shiki-light:#A0ADA0;--shiki-dark:#758575DD&quot;&gt;   # 行に沿って:  44 ms&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#393A34;--shiki-dark:#DBD7CAEE&quot;&gt;s &lt;/span&gt;&lt;span style=&quot;--shiki-light:#999999;--shiki-dark:#666666&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--shiki-light:#2F798A;--shiki-dark:#4C9A91&quot;&gt; 0.0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#1E754F;--shiki-dark:#4D9375&quot;&gt;for&lt;/span&gt;&lt;span style=&quot;--shiki-light:#393A34;--shiki-dark:#DBD7CAEE&quot;&gt; j &lt;/span&gt;&lt;span style=&quot;--shiki-light:#1E754F;--shiki-dark:#4D9375&quot;&gt;in&lt;/span&gt;&lt;span style=&quot;--shiki-light:#998418;--shiki-dark:#B8A965&quot;&gt; range&lt;/span&gt;&lt;span style=&quot;--shiki-light:#999999;--shiki-dark:#666666&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--shiki-light:#2F798A;--shiki-dark:#4C9A91&quot;&gt;8192&lt;/span&gt;&lt;span style=&quot;--shiki-light:#999999;--shiki-dark:#666666&quot;&gt;):&lt;/span&gt;&lt;span style=&quot;--shiki-light:#393A34;--shiki-dark:#DBD7CAEE&quot;&gt; s &lt;/span&gt;&lt;span style=&quot;--shiki-light:#999999;--shiki-dark:#666666&quot;&gt;+=&lt;/span&gt;&lt;span style=&quot;--shiki-light:#393A34;--shiki-dark:#DBD7CAEE&quot;&gt; M&lt;/span&gt;&lt;span style=&quot;--shiki-light:#999999;--shiki-dark:#666666&quot;&gt;[:,&lt;/span&gt;&lt;span style=&quot;--shiki-light:#393A34;--shiki-dark:#DBD7CAEE&quot;&gt; j&lt;/span&gt;&lt;span style=&quot;--shiki-light:#999999;--shiki-dark:#666666&quot;&gt;].&lt;/span&gt;&lt;span style=&quot;--shiki-light:#393A34;--shiki-dark:#DBD7CAEE&quot;&gt;sum&lt;/span&gt;&lt;span style=&quot;--shiki-light:#999999;--shiki-dark:#666666&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;--shiki-light:#A0ADA0;--shiki-dark:#758575DD&quot;&gt;   # 列を下って: 597 ms&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;同じバイト列、同じ加算で、&lt;strong&gt;13.6倍&lt;/strong&gt;の差。行パスはプリフェッチャの後ろでキャッシュラインを丸ごとストリームする。列パスはそのパスで開いたライン1本につき double を1個しか使わず、しかも 64 KB ストライドが列1本につき8192の異なるページに触れる — TLB の容量をはるかに超え、キャッシュミスの上にページウォークの代金まで払う。(隣の列があとで各ラインの残り7個を L3 から回収する — ペナルティが13.6倍で済んでいるのはそのためだ。)行パスは 537 MB を44 msで運ぶ — 約 &lt;strong&gt;12.2 GB/s&lt;/strong&gt;、このコアの実効読み取り帯域である。この数字を覚えておいてほしい。&lt;/p&gt;
&lt;h2 id=&quot;演算強度--素朴なループが速くなれない理由&quot;&gt;演算強度 — 素朴なループが速くなれない理由&lt;/h2&gt;
&lt;p&gt;コアを縛る天井はふたつ: 計算の速さと、供給の速さだ。このコアは 4.2 GHz、256ビット FMA ポート2本で、倍精度のピークは&lt;/p&gt;
&lt;span class=&quot;katex-display&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot; display=&quot;block&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mn&gt;4.2&lt;/mn&gt;&lt;mtext&gt; GHz&lt;/mtext&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;mtext&gt; &lt;/mtext&gt;&lt;mstyle scriptlevel=&quot;0&quot; displaystyle=&quot;false&quot;&gt;&lt;mfrac&gt;&lt;mtext&gt;FMA&lt;/mtext&gt;&lt;mtext&gt;cycle&lt;/mtext&gt;&lt;/mfrac&gt;&lt;/mstyle&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mn&gt;4&lt;/mn&gt;&lt;mtext&gt; &lt;/mtext&gt;&lt;mstyle scriptlevel=&quot;0&quot; displaystyle=&quot;false&quot;&gt;&lt;mfrac&gt;&lt;mtext&gt;double&lt;/mtext&gt;&lt;mtext&gt;FMA&lt;/mtext&gt;&lt;/mfrac&gt;&lt;/mstyle&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;mtext&gt; &lt;/mtext&gt;&lt;mstyle scriptlevel=&quot;0&quot; displaystyle=&quot;false&quot;&gt;&lt;mfrac&gt;&lt;mtext&gt;FLOP&lt;/mtext&gt;&lt;mtext&gt;double&lt;/mtext&gt;&lt;/mfrac&gt;&lt;/mstyle&gt;&lt;mtext&gt;  &lt;/mtext&gt;&lt;mo&gt;≈&lt;/mo&gt;&lt;mtext&gt;  &lt;/mtext&gt;&lt;mn&gt;67&lt;/mn&gt;&lt;mtext&gt; &lt;/mtext&gt;&lt;mstyle scriptlevel=&quot;0&quot; displaystyle=&quot;false&quot;&gt;&lt;mfrac&gt;&lt;mtext&gt;GFLOP&lt;/mtext&gt;&lt;mtext&gt;s&lt;/mtext&gt;&lt;/mfrac&gt;&lt;/mstyle&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;4.2\ \text{GHz} \times 2\ \tfrac{\text{FMA}}{\text{cycle}} \times 4\ \tfrac{\text{double}}{\text{FMA}} \times 2\ \tfrac{\text{FLOP}}{\text{double}}
\;\approx\; 67\ \tfrac{\text{GFLOP}}{\text{s}}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;— だが持続できる読み取りは約 12.2 GB/s しかない。どちらの天井が効くかを決めるのが&lt;strong&gt;演算強度&lt;/strong&gt;: 移動1バイトあたりに実行する FLOP 数である。&lt;/p&gt;
&lt;p&gt;素朴なループは — オペランドがキャッシュを超えたサイズでは — 両オペランドを使うたびにコアへ流し直す。積和1回につき8バイトの読み取りが2回、強度は &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;q&lt;/mi&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mstyle scriptlevel=&quot;0&quot; displaystyle=&quot;false&quot;&gt;&lt;mfrac&gt;&lt;mrow&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;mtext&gt; FLOP&lt;/mtext&gt;&lt;/mrow&gt;&lt;mrow&gt;&lt;mn&gt;16&lt;/mn&gt;&lt;mtext&gt; B&lt;/mtext&gt;&lt;/mrow&gt;&lt;/mfrac&gt;&lt;/mstyle&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mn&gt;0.125&lt;/mn&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;q = \tfrac{2\ \text{FLOP}}{16\ \text{B}} = 0.125&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;/span&gt;。12.2 GB/s のもとでは、このアクセスパターンである限り&lt;em&gt;完全にベクトル化された&lt;/em&gt;ループでさえ &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mn&gt;0.125&lt;/mn&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mn&gt;12.2&lt;/mn&gt;&lt;mo&gt;≈&lt;/mo&gt;&lt;mn&gt;1.5&lt;/mn&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;0.125 \times 12.2 \approx 1.5&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;/span&gt; GFLOP/s 前後で頭打ちになる — 計算ピークの40分の1以下、インタープリタの1サイクルを数える前の話だ。この天井はコンパイルでは持ち上がらない。ループ&lt;em&gt;そのもの&lt;/em&gt;が、構造からしてメモリ律速なのである。&lt;/p&gt;
&lt;p&gt;速くなるために必要なのは FLOP を減らすことではない。&lt;strong&gt;1バイトあたりの&lt;/strong&gt; FLOP を増やすことだ。&lt;/p&gt;
&lt;h2 id=&quot;ブロッキング-m-のアイデア&quot;&gt;ブロッキング: √M のアイデア&lt;/h2&gt;
&lt;p&gt;処方箋は何十年も前からあり、今もあらゆる BLAS とあらゆる GPU 行列積カーネルを支えている: &lt;strong&gt;小さなワーキングセットをキャッシュに常駐させ、追い出される前に再利用されるよう、問題をタイルに切れ&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;行列を &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;b \times b&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;/span&gt; のタイルに切り、&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;C&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;/span&gt; の各タイルを小さなタイル積の和として累積する:&lt;/p&gt;
&lt;pre class=&quot;astro-code astro-code-themes vitesse-light vitesse-dark&quot; style=&quot;--shiki-light:#393a34;--shiki-dark:#dbd7caee;--shiki-light-bg:#ffffff;--shiki-dark-bg:#121212; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;python&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#1E754F;--shiki-dark:#4D9375&quot;&gt;for&lt;/span&gt;&lt;span style=&quot;--shiki-light:#393A34;--shiki-dark:#DBD7CAEE&quot;&gt; i0 &lt;/span&gt;&lt;span style=&quot;--shiki-light:#1E754F;--shiki-dark:#4D9375&quot;&gt;in&lt;/span&gt;&lt;span style=&quot;--shiki-light:#998418;--shiki-dark:#B8A965&quot;&gt; range&lt;/span&gt;&lt;span style=&quot;--shiki-light:#999999;--shiki-dark:#666666&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--shiki-light:#2F798A;--shiki-dark:#4C9A91&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;--shiki-light:#999999;--shiki-dark:#666666&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--shiki-light:#393A34;--shiki-dark:#DBD7CAEE&quot;&gt; n&lt;/span&gt;&lt;span style=&quot;--shiki-light:#999999;--shiki-dark:#666666&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--shiki-light:#393A34;--shiki-dark:#DBD7CAEE&quot;&gt; b&lt;/span&gt;&lt;span style=&quot;--shiki-light:#999999;--shiki-dark:#666666&quot;&gt;):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#1E754F;--shiki-dark:#4D9375&quot;&gt;    for&lt;/span&gt;&lt;span style=&quot;--shiki-light:#393A34;--shiki-dark:#DBD7CAEE&quot;&gt; j0 &lt;/span&gt;&lt;span style=&quot;--shiki-light:#1E754F;--shiki-dark:#4D9375&quot;&gt;in&lt;/span&gt;&lt;span style=&quot;--shiki-light:#998418;--shiki-dark:#B8A965&quot;&gt; range&lt;/span&gt;&lt;span style=&quot;--shiki-light:#999999;--shiki-dark:#666666&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--shiki-light:#2F798A;--shiki-dark:#4C9A91&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;--shiki-light:#999999;--shiki-dark:#666666&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--shiki-light:#393A34;--shiki-dark:#DBD7CAEE&quot;&gt; n&lt;/span&gt;&lt;span style=&quot;--shiki-light:#999999;--shiki-dark:#666666&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--shiki-light:#393A34;--shiki-dark:#DBD7CAEE&quot;&gt; b&lt;/span&gt;&lt;span style=&quot;--shiki-light:#999999;--shiki-dark:#666666&quot;&gt;):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#A0ADA0;--shiki-dark:#758575DD&quot;&gt;        # この C タイルは p ループの間ずっと再利用される&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#1E754F;--shiki-dark:#4D9375&quot;&gt;        for&lt;/span&gt;&lt;span style=&quot;--shiki-light:#393A34;--shiki-dark:#DBD7CAEE&quot;&gt; p0 &lt;/span&gt;&lt;span style=&quot;--shiki-light:#1E754F;--shiki-dark:#4D9375&quot;&gt;in&lt;/span&gt;&lt;span style=&quot;--shiki-light:#998418;--shiki-dark:#B8A965&quot;&gt; range&lt;/span&gt;&lt;span style=&quot;--shiki-light:#999999;--shiki-dark:#666666&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--shiki-light:#2F798A;--shiki-dark:#4C9A91&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;--shiki-light:#999999;--shiki-dark:#666666&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--shiki-light:#393A34;--shiki-dark:#DBD7CAEE&quot;&gt; n&lt;/span&gt;&lt;span style=&quot;--shiki-light:#999999;--shiki-dark:#666666&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--shiki-light:#393A34;--shiki-dark:#DBD7CAEE&quot;&gt; b&lt;/span&gt;&lt;span style=&quot;--shiki-light:#999999;--shiki-dark:#666666&quot;&gt;):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#393A34;--shiki-dark:#DBD7CAEE&quot;&gt;            C&lt;/span&gt;&lt;span style=&quot;--shiki-light:#999999;--shiki-dark:#666666&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;--shiki-light:#393A34;--shiki-dark:#DBD7CAEE&quot;&gt;i0&lt;/span&gt;&lt;span style=&quot;--shiki-light:#999999;--shiki-dark:#666666&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;--shiki-light:#393A34;--shiki-dark:#DBD7CAEE&quot;&gt;i0&lt;/span&gt;&lt;span style=&quot;--shiki-light:#AB5959;--shiki-dark:#CB7676&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;--shiki-light:#393A34;--shiki-dark:#DBD7CAEE&quot;&gt;b&lt;/span&gt;&lt;span style=&quot;--shiki-light:#999999;--shiki-dark:#666666&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--shiki-light:#393A34;--shiki-dark:#DBD7CAEE&quot;&gt; j0&lt;/span&gt;&lt;span style=&quot;--shiki-light:#999999;--shiki-dark:#666666&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;--shiki-light:#393A34;--shiki-dark:#DBD7CAEE&quot;&gt;j0&lt;/span&gt;&lt;span style=&quot;--shiki-light:#AB5959;--shiki-dark:#CB7676&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;--shiki-light:#393A34;--shiki-dark:#DBD7CAEE&quot;&gt;b&lt;/span&gt;&lt;span style=&quot;--shiki-light:#999999;--shiki-dark:#666666&quot;&gt;]&lt;/span&gt;&lt;span style=&quot;--shiki-light:#999999;--shiki-dark:#666666&quot;&gt; +=&lt;/span&gt;&lt;span style=&quot;--shiki-light:#393A34;--shiki-dark:#DBD7CAEE&quot;&gt; A&lt;/span&gt;&lt;span style=&quot;--shiki-light:#999999;--shiki-dark:#666666&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;--shiki-light:#393A34;--shiki-dark:#DBD7CAEE&quot;&gt;i0&lt;/span&gt;&lt;span style=&quot;--shiki-light:#999999;--shiki-dark:#666666&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;--shiki-light:#393A34;--shiki-dark:#DBD7CAEE&quot;&gt;i0&lt;/span&gt;&lt;span style=&quot;--shiki-light:#AB5959;--shiki-dark:#CB7676&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;--shiki-light:#393A34;--shiki-dark:#DBD7CAEE&quot;&gt;b&lt;/span&gt;&lt;span style=&quot;--shiki-light:#999999;--shiki-dark:#666666&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--shiki-light:#393A34;--shiki-dark:#DBD7CAEE&quot;&gt; p0&lt;/span&gt;&lt;span style=&quot;--shiki-light:#999999;--shiki-dark:#666666&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;--shiki-light:#393A34;--shiki-dark:#DBD7CAEE&quot;&gt;p0&lt;/span&gt;&lt;span style=&quot;--shiki-light:#AB5959;--shiki-dark:#CB7676&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;--shiki-light:#393A34;--shiki-dark:#DBD7CAEE&quot;&gt;b&lt;/span&gt;&lt;span style=&quot;--shiki-light:#999999;--shiki-dark:#666666&quot;&gt;]&lt;/span&gt;&lt;span style=&quot;--shiki-light:#AB5959;--shiki-dark:#CB7676&quot;&gt; @&lt;/span&gt;&lt;span style=&quot;--shiki-light:#393A34;--shiki-dark:#DBD7CAEE&quot;&gt; B&lt;/span&gt;&lt;span style=&quot;--shiki-light:#999999;--shiki-dark:#666666&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;--shiki-light:#393A34;--shiki-dark:#DBD7CAEE&quot;&gt;p0&lt;/span&gt;&lt;span style=&quot;--shiki-light:#999999;--shiki-dark:#666666&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;--shiki-light:#393A34;--shiki-dark:#DBD7CAEE&quot;&gt;p0&lt;/span&gt;&lt;span style=&quot;--shiki-light:#AB5959;--shiki-dark:#CB7676&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;--shiki-light:#393A34;--shiki-dark:#DBD7CAEE&quot;&gt;b&lt;/span&gt;&lt;span style=&quot;--shiki-light:#999999;--shiki-dark:#666666&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--shiki-light:#393A34;--shiki-dark:#DBD7CAEE&quot;&gt; j0&lt;/span&gt;&lt;span style=&quot;--shiki-light:#999999;--shiki-dark:#666666&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;--shiki-light:#393A34;--shiki-dark:#DBD7CAEE&quot;&gt;j0&lt;/span&gt;&lt;span style=&quot;--shiki-light:#AB5959;--shiki-dark:#CB7676&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;--shiki-light:#393A34;--shiki-dark:#DBD7CAEE&quot;&gt;b&lt;/span&gt;&lt;span style=&quot;--shiki-light:#999999;--shiki-dark:#666666&quot;&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;内側ループの1ステップが触るのは &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;b \times b&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;/span&gt; タイル3枚 — &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mn&gt;3&lt;/mn&gt;&lt;msup&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;/msup&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mn&gt;8&lt;/mn&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;3b^2 \times 8&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;/span&gt; バイト — で、その上で &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;msup&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mn&gt;3&lt;/mn&gt;&lt;/msup&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;2b^3&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;/span&gt; FLOP を実行する:&lt;/p&gt;
&lt;span class=&quot;katex-display&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot; display=&quot;block&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;q&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mtext&gt;  &lt;/mtext&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mtext&gt;  &lt;/mtext&gt;&lt;mfrac&gt;&lt;mrow&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;msup&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mn&gt;3&lt;/mn&gt;&lt;/msup&gt;&lt;/mrow&gt;&lt;mrow&gt;&lt;mn&gt;24&lt;/mn&gt;&lt;mtext&gt; &lt;/mtext&gt;&lt;msup&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;/msup&gt;&lt;/mrow&gt;&lt;/mfrac&gt;&lt;mtext&gt; &lt;/mtext&gt;&lt;mstyle scriptlevel=&quot;0&quot; displaystyle=&quot;false&quot;&gt;&lt;mfrac&gt;&lt;mtext&gt;FLOP&lt;/mtext&gt;&lt;mtext&gt;B&lt;/mtext&gt;&lt;/mfrac&gt;&lt;/mstyle&gt;&lt;mtext&gt;  &lt;/mtext&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mtext&gt;  &lt;/mtext&gt;&lt;mfrac&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mn&gt;12&lt;/mn&gt;&lt;/mfrac&gt;&lt;mtext&gt; &lt;/mtext&gt;&lt;mstyle scriptlevel=&quot;0&quot; displaystyle=&quot;false&quot;&gt;&lt;mfrac&gt;&lt;mtext&gt;FLOP&lt;/mtext&gt;&lt;mtext&gt;B&lt;/mtext&gt;&lt;/mfrac&gt;&lt;/mstyle&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;q(b) \;=\; \frac{2b^3}{24\, b^2}\ \tfrac{\text{FLOP}}{\text{B}} \;=\; \frac{b}{12}\ \tfrac{\text{FLOP}}{\text{B}},&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;強度が&lt;em&gt;タイルサイズとともに育つ&lt;/em&gt;。このコアをメモリ律速から計算律速へ持ち上げるには &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;q&lt;/mi&gt;&lt;mo&gt;≳&lt;/mo&gt;&lt;mn&gt;67&lt;/mn&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;/&lt;/mi&gt;&lt;mn&gt;12.2&lt;/mn&gt;&lt;mo&gt;≈&lt;/mo&gt;&lt;mn&gt;5.5&lt;/mn&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;q \gtrsim 67 / 12.2 \approx 5.5&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;/span&gt;、つまり &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;b&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;/span&gt; はおよそ70 — そして float64 の 70×70 タイル3枚は 118 KB、256 KB の L2 に余裕で収まる。トリックはこれだけであり、この分野の文献でキャッシュ容量 &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;M&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;M&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;/span&gt; がいつも平方根の下に現れるのはそのためだ。一辺 &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mo&gt;∼&lt;/mo&gt;&lt;msqrt&gt;&lt;mrow&gt;&lt;mi&gt;M&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;/&lt;/mi&gt;&lt;mn&gt;3&lt;/mn&gt;&lt;/mrow&gt;&lt;/msqrt&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;b \sim \sqrt{M/3}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;/span&gt; のタイルは、総トラフィックを素朴な &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;script&quot;&gt;O&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;msup&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mn&gt;3&lt;/mn&gt;&lt;/msup&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\mathcal{O}(n^3)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;/span&gt; ワードから&lt;/p&gt;
&lt;span class=&quot;katex-display&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot; display=&quot;block&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;script&quot;&gt;O&lt;/mi&gt;&lt;mtext&gt; ⁣&lt;/mtext&gt;&lt;mrow&gt;&lt;mo fence=&quot;true&quot;&gt;(&lt;/mo&gt;&lt;mfrac&gt;&lt;msup&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mn&gt;3&lt;/mn&gt;&lt;/msup&gt;&lt;msqrt&gt;&lt;mi&gt;M&lt;/mi&gt;&lt;/msqrt&gt;&lt;/mfrac&gt;&lt;mo fence=&quot;true&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\mathcal{O}\!\left(\frac{n^3}{\sqrt{M}}\right)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;まで削る。これが古典アルゴリズムのどんな実行順序についても漸近最適であることは、Hong と Kung が1981年に証明した。キャッシュが大きいほどトラフィックは少ない — 平方根のぶんだけ。&lt;/p&gt;
&lt;h2 id=&quot;本物のblasが加えるもの&quot;&gt;本物のBLASが加えるもの&lt;/h2&gt;
&lt;p&gt;OpenBLAS はこのアイデアを執念で実装したものだ。キャッシュ階層ごとに調律されたタイルサイズ、オペランドの&lt;em&gt;パッキング&lt;/em&gt;(各タイルを連続かつアラインされたバッファへコピーし、&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;B&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;/span&gt; の下降さえライン単位の逐次ストリームに変える)、そして &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;C&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;/span&gt; の小ブロックをベクトルレジスタに置いたまま FMA を流し続ける最内側のレジスタ・マイクロカーネル。成果はグラフ1枚に収まる:&lt;/p&gt;
&lt;figure class=&quot;fig-light&quot;&gt;&lt;a href=&quot;https://latentstate.dev/ja/posts/matrix-multiplication/&quot;&gt;[図 — サイトで見る]&lt;/a&gt;&lt;figcaption&gt;図2 — 1スレッドの A @ B をサイズ横断で計測。平坦な線こそがすべて&lt;/figcaption&gt;&lt;/figure&gt;

&lt;p&gt;&lt;strong&gt;平坦だ。&lt;/strong&gt; 3枚の行列が L3 に収まる &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mn&gt;256&lt;/mn&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;n = 256&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;/span&gt; から、268 MB のオペランド(結果も数えれば 400 MB)が DRAM に置かれる &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mn&gt;4096&lt;/mn&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;n = 4096&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;/span&gt; まで、スループットは 51〜54 GFLOP/s — 最大サイズで理論1コアピークの79% — を保つ。ブロッキングが FLOP対バイト比を、問題サイズではなく&lt;em&gt;タイル&lt;/em&gt;の性質にしてしまうからだ。定義どおりのループは、行列がキャッシュ階層をひとつ超えるたびに、1 FLOP あたりの時間が延びていく。ブロック化されたループは意に介さない。&lt;/p&gt;
&lt;p&gt;同じマシンからの脚注をふたつ、どちらも実測で。第一に並列性: 物理4コアに固定すると &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mn&gt;4096&lt;/mn&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;n = 4096&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;/span&gt; は &lt;strong&gt;179 GFLOP/s&lt;/strong&gt; — 3.4倍のスピードアップで、4倍に届かないぶんの主因はシングルコアターボより低い全コアターボ、それに L3 と DRAM チャネルの共有だ。デフォルト設定のままだと OpenBLAS はこのマシンで8スレッド — &lt;em&gt;ハイパースレッド&lt;/em&gt;1本につき1スレッド — を立ち上げ、118 GFLOP/s まで落ちる。2本の SMT 兄弟スレッドは同じ物理コアの FMA パイプを分け合うので、余分なスレッドはスケジューリングのコストだけ足して計算を1つも足さない。数えるべきは物理コアである。第二に、ピークの79%という数字: これは成熟した BLAS がこのマイクロアーキテクチャの float64 で到達する水準で、欠けた2割はパッキングのトラフィック、タイルの端、ループの管理に消える。100%は誰にも出せない。&lt;/p&gt;
&lt;h2 id=&quot;同じアイデアがいちばん上まで&quot;&gt;同じアイデアが、いちばん上まで&lt;/h2&gt;
&lt;p&gt;「L2」を「シェアードメモリ」に置き換えれば、これは CUDA の講義になる。GPU の行列積カーネルは &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;A&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;/span&gt; と &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;B&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;/span&gt; のタイルを各 SM のシェアードメモリに載せ、同期し、乗算し、進む — 同じ &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msqrt&gt;&lt;mi&gt;M&lt;/mi&gt;&lt;/msqrt&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\sqrt{M}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;/span&gt; の議論を、数千のスレッドが実行しているだけだ。テンソルコアはタイルをデータパスそのものに取り込む。ワープが固定サイズのフラグメントを供給し、ハードウェアが小さな密行列積を1命令として実行する。さらに一段上では、アテンション層も MLP ブロックもこうした積の&lt;em&gt;バッチ&lt;/em&gt;であり、だからこそ演算強度 — いまでは「重み1バイトあたりの FLOP」と言い換えられることが多い — が、H100 上のトランスフォーマーが計算律速か帯域律速かを今日も決めている。&lt;/p&gt;
&lt;p&gt;定義は3重ループのまま、ビネが1812年に「行×列」の規則を書き下して以来、本質的に変わっていない。9.3秒と5.1ミリ秒のあいだにあるものはすべて、自分のキャッシュラインがどこにあるかを知っているかどうかだ。&lt;/p&gt;
&lt;details&gt;
&lt;summary&gt;再現する&lt;/summary&gt;
&lt;p&gt;&lt;a href=&quot;/code/matmul_bench.py&quot;&gt;&lt;code&gt;matmul_bench.py&lt;/code&gt;&lt;/a&gt; — 標準ライブラリと NumPy だけの約130行の Python。遅い2つのループ(1回実行)、BLAS のサイズスイープとトラバーサルのデモ(ベスト・オブ・5)、マルチスレッド計測、すべて固定シード。計測対象は上に示した関数そのものだ。絶対値はあなたのマシンでは違ってくるが、比率は違わない。信じる前に、走らせてほしい。&lt;/p&gt;
&lt;/details&gt;</content:encoded></item></channel></rss>