Next: Assembly Functional Units, Previous: Assembly Carry Propagation, Up: Assembly Coding [Index]
GMPは,オペランド(被演算数)がL1キャッシュに入り切るかどうかに関わらず,高速に演算を行うように設計されています。
mpn_add_n
や mpn_lshift
のような基盤関数は大きな桁の演算に利用されることが多く,
L2キャッシュやメインメモリのパフォーマンスがこれらの関数に大きな影響を与えます。
mpn_mul_1
関数 や mpn_addmul_1
関数は筆算乗算や筆算二乗では頻繁に利用されるので,
mpn_mul_basecase
関数や mpn_sqr_basecase
関数のアセンブラバージョンの有無に関わらず,L1キャッシュのパフォーマンスが効いてきます。この二つの関数は大きな桁の演算にも良く利用されます。
L2キャッシュやメインメモリ関数に対しては,演算回数よりも,メモリアクセスの回数が確実に多くなります。従って, メモリスループットを最大化することを目標に,次のキャッシュラインから呼び出すようにするとともに,一度呼びだしたデータを 再使用するようにします。CPUがロックアップフリーキャッシュや先読み命令を持っているのであれば,スループットを向上させることができるでしょう。現在のCPUは大概この両方を持っています。
先読み命令はループ展開と相性が良く,展開されたループ1回ごとに先読みが初期化されます(ループがキャッシュラインを複数カバーしていれば2回以上初期化される)。
書き込み用に確保されたキャッシュがないCPUの場合,先読みされる先は個別に書きこまれますので,キャッシュ階層の下に下がってくることはなく,(メインメモリの)バンド幅の制約を受けます。当然mpn_divrem_1
のような関数の計算は遅くなりますので,書き込みスループットが重要になってきます。
先読み命令の間隔は,メモリレイテンシとスループットの兼ね合いで決まってきます。目的は当然,データを連続的に受け付けることなので, ピーク性能はスループットになります。ある種のCPUはフェッチ数と先読み数に実行中の制約が存在します。
特別な先読み命令が存在していない場合は,生のロード命令が使われますので,過去に読み込まれたオペランドを最後から読み取ろうとはしません。従って,セグメンテーション違反が発生してしまう可能性があります。
ある種のCPUやシステムにはシーケンシャルメモリアクセスを検知するハードウェアを持っており,これによって自動的にキャッシュの動作を初期化することができ,利便性が高まります。