Gen 4×4 SSD を Gen 4 マザーボードに接続しても、必ずしも約 8 GB/s の帯域を独占できるわけではありません。スロットにはレーンが 2 本しか接続されていない場合や、スイッチチップやチップセットを介して他のデバイスとアップリンクを共有している可能性があります。パフォーマンスを説明するには、実際のトポロジをまず図示し、リンクレート、符号化後の帯域幅、トランザクションオーバーヘッド、およびデバイスの処理速度を区別する必要があります。
確認すべき問題 この記事の入り口 重要な定義
x4/x16 は何を数えているのか レーンとリンク 1つのレーンには双方向の差動チャネルがあり、複数のレーンで1つのリンクを構成する
各世代でどれくらい伝送できるか レートと符号化 単方向、10進数の GB/s、オーバーヘッドを控除済みか否か
なぜ複数のデバイスが同時に遅くなるのか トポロジと共有アップリンク 各ホップにおけるリンクとトラフィックの方向
なぜ読み書きでパフォーマンスが異なるのか TLP と在途要求 posted write、read completion、レイテンシと並行性
デバイスがなぜ低速化したり検出されなかったりするのか トレーニングと列挙 電気的状態、リソース割り当て、ドライバと DMA
レーンは物理的な並列度、Generation はリンクレートのレベル
1つのレーンには、1対の送信差動線と1対の受信差動線が含まれており、2つの方向で同時に動作します。x4 リンクは4本のレーンを組み合わせて伝送しますが、これは4つの独立してアドレス指定可能なデバイスではありません。x16 の高速信号は合計 16×4=64 本の導線を持ちますが、電源、グランド、参照クロック、およびサイドバンド制御は含まれません。
スロットの機械的な長さ、電気的な配線、および現在ネゴシエートされた幅は異なる場合があります。x16 の長いスロットでも x4 しか接続されていない可能性があります。マザーボードは、別のデバイスを挿入した後にポートリソースを再割り当てすることもあります。 bifurcation(分割)をサポートするルートポートは、1組のレーンを複数の独立したリンクに構成できますが、パッシブなアダプタボード自体が PCIe スイッチ機能を自然に実現するわけではなく、ファームウェアとハードウェアの両方が対応する分割をサポートする必要があります。
帯域幅はまず単方向で宣言され、その後対応する世代のオーバーヘッドが差し引かれる
以下の Gen 1~5 の数値は、ライン符号化を差し引いたものですが、トランザクションパケット、リンク制御、その他のオーバーヘッドは差し引かれていません 。GB は 10⁹ バイト(10進数)を使用し、GiB ではありません。
ジェネレーション 公称伝送レート 信号/符号化概要 1レーンあたりの単方向予算 x16 単方向予算
Gen 1 2.5 GT/s NRZ、8b/10b 0.250 GB/s 4.000 GB/s
Gen 2 5 GT/s NRZ、8b/10b 0.500 GB/s 8.000 GB/s
Gen 3 8 GT/s NRZ、128b/130b 0.985 GB/s 15.754 GB/s
Gen 4 16 GT/s NRZ、128b/130b 1.969 GB/s 31.508 GB/s
Gen 5 32 GT/s NRZ、128b/130b 3.938 GB/s 63.015 GB/s
Gen 6 64 GT/s PAM4、FLIT/FEC 原始ビットレート換算で 8 GB/s、FLIT オーバーヘッド未控除 原始 128 GB/s、FLIT オーバーヘッド未控除
Gen 7 128 GT/s PAM4、FLIT/FEC 原始ビットレート換算で 16 GB/s、FLIT オーバーヘッド未控除 原始 256 GB/s、FLIT オーバーヘッド未控除
例えば Gen 4×4 の場合:16×10⁹×128/130×4/8≈7.877×10⁹ バイト/秒。フルデュプレックスとは、もう一方の方向にも同様の能力があることを意味し、双方向と 15.754 GB/s を1回の単方向 SSD 読み取りの上限として扱うことはできません。
Gen 6 の 64 GT/s は PAM4 を使用し、1つのシンボルで2ビットを伝送します。シンボルレートは公称 GT/s と NRZ のように1対1で対応しなくなります。固定の 256 バイト FLIT を採用し、誤り訂正などのメカニズムを追加しているため、128/130 を掛けるだけでは最終的な有効帯域幅とは言えません。1つの FLIT の TLP 領域には複数のトランザクションパケットを格納でき、領域内にはトランザクションヘッダーやパディングが含まれる可能性があり、アプリケーションの純粋なペイロードは FLIT のサイズ全体に直接等しくなりません。PCI-SIG:FLIT、PAM4、および FEC
PCIe 7.0 の 128 GT/s 仕様は 2025 年 6 月にリリースされました。仕様のリリース、コントローラのサポート、量産マザーボード、および特定のマシンでの実際のリンク能力は異なる状態であり、仕様の世代だけで現在のデバイスの利用可能なレートを推測してはいけません。PCI-SIG:PCIe 7.0 リリース
トポロジ:各セグメントはポイントツーポイントだが、システム全体ではボトルネックを共有する可能性がある
Root Complex はプロセッサ/メモリシステムを PCIe 階層に接続し、Root Port は対応するポートです。Endpoint はデバイス機能を提供します。Switch はアップリンクとダウンリンクポートで階層を拡張し、トランザクションをルーティングしますが、すべてのダウンリンクポートが個別に完全な独占アップリンクを得るわけではありません。
Root Port ホストメモリへ PCIe Switch 経路に応じて転送 Gen 4 ×4 共有アップリンク SSD A Gen 4 ×4 SSD B Gen 4 ×4 2つのダウンリンク x4 が、1つのアップリンク x4 を x8 にするわけではない 2つの SSD がホストへの同方向アクセス:合計は依然としてアップリンクの符号化後上限約 7.877 GB/s に 制約される パケットオーバーヘッドを無視した教育的トポロジ;デバイス間 P2P、スイッチパス、およびプラットフォームルーティ ングポリシーは個別に分析する必要がある。
2つの SSD がそれぞれ Gen 4×4 のダウンリンクを持ち、Gen 4×4 のアップリンクを共有し、同時にホストメモリへ 5 GB/s で転送する場合、合計必要量は 10 GB/s となり、アップリンクの符号化後上限である約 7.877 GB/s を超えています。他のオーバーヘッドを無視しても、各 SSD が長期的に 5 GB/s を維持することは不可能です。実際の割り当てはアービトレーションとトラフィックに依存し、必ずしも厳密に半分ずつになるとは限りません。
チップセットの下に接続されたストレージ、ネットワーク、USB もホストインターコネクトを共有する可能性があります。Intel DMI や異なる AMD プラットフォームのチップセット接続には、それぞれ独自の幅と実装があり、「DMI は本質的に PCIe x8 である」などと固定して描いたり、AMD チップセットのアップリンクを Infinity Fabric と直接同一視したりすることはできません。特定のプロセッサとマザーボードのブロック図を確認することが、あるブランドの統一されたレーン数だけを暗記するよりも信頼できます。
P2P トランザクションはローカル階層で転送される場合もあれば、プラットフォーム、ACS、IOMMU、またはドライバのサポートにより制限される場合もあります。同じ Switch が見えていても、2つのデバイス間のすべての DMA が直接実行できるわけではありません。カーネル内の PCIe ドライバモデル
3層プロトコル:リンクが正しく受信しても、デバイスがビジネスロジックを完了したわけではない
レイヤー 主な責任 教育的に混同されやすい境界
Transaction メモリ読み書き、設定アクセス、メッセージなどの TLP 要求の完了とデータの永続化は同義語ではない
Data Link 隣接リンク間の信頼性のある伝達、フロー制御関連メカニズム エンドツーエンドのビジネス確認ではない
Physical シリアル送受信、トレーニング、符号化、および電気的リンク トレーニングの成功がドライバの準備完了を意味するわけではない
一般的な非 FLIT モードでは、リンク層はシーケンス番号、LCRC、および ACK/NAK リプレイメカニズムを使用します。Gen 6 FLIT モードでは保護とリプレイの単位が異なるため、古いパケットフォーマットをそのまま一般化することはできません。誤り訂正/リプレイも帯域幅を消費するため、繰り返し修正可能なエラーを「パフォーマンスに影響がない」と単純に扱うべきではありません。
メモリ書き込みは通常 posted request であり、対応するトランザクション Completion の返却を要求しません。メモリ読み込みは non-posted request であり、Completion の返却が必要で、通常はデータも伴います。Completion がないからといって、書き込みがすべての操作を無秩序に飛び越えられるわけではなく、さらに SSD への書き込みが完了したことを意味するわけではありません。レジスタ読み戻し、DMA バリア、デバイスコマンドの完了、およびストレージの永続化は、それぞれ異なる保証レベルに属します。
Requester Completer Memory Read、Tag 0、256 B を要求 Memory Read、Tag 1、256 B を要求 Completion with Data、Tag 0 Completion with Data、Tag 1 メモリ読み込みには Completion の返却が必要:往復レイテンシをカバーするため に複数の未完了の要求を維持する Tag は未完了の要求のマッチングに使用されます。1つの要求は複数の Completion で返される可能性があり、返却順序と 制限はプロトコルに従って処理されます。
Requester は Tag を使用して未完了の読み込み要求を管理し、1つの要求が複数の Completion に分割される場合があります。読み込みスループットはリンクレートだけでなく、在途状態にできるデータ量と往復レイテンシにも制限されます。32 筆を許可し、各筆が 256 B、平均往復レイテンシが 2 μs と仮定すると、理想的なウィンドウ上限は約 32×256/2μs=4.096 GB/s となり、リンクの利用可能帯域幅がそれ以上にあっても埋まらない可能性があります。並行性を増やすことで改善できますが、Tag、バッファ、クレジット、デバイス、およびメモリの制限にも直面します。Intel:PCIe スループットに影響を与える要因
MPS はトランザクションパケットの最大データペイロードを制限し、MRRS は読み込み要求の最大サイズを制限します。これらは同一のパラメータではありません。より大きな要求でも複数の Completion に分割される可能性があります。これらの値を調整するには、パス全体とデバイスの能力に適合させる必要があり、「一律に最大値に設定すれば最速になる」とは限りません。
リンクが空いていてもデータを待つ理由は?
既定の32要求・2 μsでは窓予算4.096 GB/s。並行数を増やすとリンク上限に達し、RTTを増やすと折点が右へ動く。これは読出しCompletion窓であり、NVMe業務読出しのPCIe方向そのものではない。
R ≤ min ( C l ink , RTT N B re q u es t )
図を準備しています 再読み込み
リンクが空いていてもデータを待つ理由は? 読出しはCompletionで窓を再利用するため、窓/RTTがリンク容量より先に制限になる。
{"id":"pcie-read-window","title":"リンクが空いていてもデータを待つ理由は?","summary":"読出しはCompletionで窓を再利用するため、窓/RTTがリンク容量より先に制限になる。","height":1000,"html":"<h2 data-i18n=\"heading\"></h2><p class=\"intro\" data-i18n=\"intro\"></p><div class=\"control\"><label for=\"count\" data-i18n=\"count\"></label><output for=\"count\" id=\"count-value\"></output><input id=\"count\" type=\"range\" min=\"1\" max=\"128\" value=\"32\" step=\"1\"></div><div class=\"control\"><label for=\"rtt\" data-i18n=\"rtt\"></label><output for=\"rtt\" id=\"rtt-value\"></output><input id=\"rtt\" type=\"range\" min=\"0.5\" max=\"8\" value=\"2\" step=\"0.1\"></div><div class=\"chart-wrap\"><div class=\"chart-label\" data-i18n=\"plot\"></div><svg id=\"plot\" class=\"curve\" viewBox=\"0 0 360 210\" role=\"img\" data-i18n-label=\"plot\"></svg></div><div class=\"metrics\"><div><span data-i18n=\"window\"></span><strong id=\"window\"></strong></div><div><span data-i18n=\"rate\"></span><strong id=\"rate\"></strong></div><div><span data-i18n=\"needed\"></span><strong id=\"needed\"></strong></div></div><p id=\"eq\" class=\"formula\"></p><details class=\"scope\"><summary data-i18n=\"scopeLabel\"></summary><p data-i18n=\"scope\"></p></details>","css":".intro{margin:8px 0 18px;color:var(--muted);font-size:14px}.caption,.hint{font-size:12px;color:var(--muted);margin-top:12px}.control{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:6px 12px;align-items:center;margin:14px 0;font-size:13px}.control label{font-size:13px}.control output{color:var(--accent);min-width:5em;text-align:right;font-variant-numeric:tabular-nums}.control input{grid-column:1/-1;width:100%;margin:0}.presets{display:flex;gap:4px;align-items:stretch}.presets button{flex:1 1 0;min-width:0;overflow-wrap:anywhere;font-size:13px}.actions{display:flex;gap:8px;flex-wrap:wrap;margin:14px 0}.actions button{flex:1;min-width:0;font-size:13px;min-height:42px}.copy{display:grid;font-size:14px;margin:16px 0}.copy>*{grid-area:1/1;margin:0}.reserve{visibility:hidden}.scope{margin-top:14px;color:var(--muted);font-size:12px}.scope summary{padding:8px 0;cursor:pointer}.scope p{margin-top:10px}.two{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px;margin:16px 0}.card{border:1px solid var(--rule);border-radius:9px;padding:14px;min-width:0}.card header{font-size:14px;font-weight:600;margin-bottom:10px}.card button{font-size:12px;width:100%;min-width:0}.card small{display:block;font-size:12px;color:var(--muted)}.card code{font-size:12px;overflow-wrap:anywhere}.metrics{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px;margin:16px 0}.metrics>div{border-left:2px solid var(--accent);padding-left:10px;min-width:0}.metrics span{display:block;min-height:3.2em;color:var(--muted);font-size:12px}.metrics strong{font-size:23px;display:block;font-weight:550;overflow-wrap:anywhere;font-variant-numeric:tabular-nums}.formula{border-top:1px solid var(--rule);padding-top:12px;margin-top:14px;font-size:13px;font-variant-numeric:tabular-nums;overflow-wrap:anywhere}.value{font:550 20px ui-monospace,monospace}.legend{display:flex;flex-wrap:wrap;gap:6px 14px;font-size:12px;color:var(--muted);margin:12px 0}.legend span:before{content:'';display:inline-block;width:8px;height:8px;border-radius:2px;background:var(--accent);margin-right:6px}.legend .second:before{background:var(--second)}.check{display:flex;align-items:center;gap:8px;font-size:13px;margin:12px 0}.check input{width:16px;height:16px;flex-shrink:0;accent-color:var(--accent)}select,input[type=text],input[type=number]{background:var(--paper);color:var(--ink);font:inherit;font-size:13px;padding:10px;border:1px solid var(--rule);border-radius:7px;max-width:100%;min-width:0}select{width:100%;min-height:42px}.band{height:20px;display:flex;background:var(--surface);border-radius:4px;overflow:hidden}.band i{height:100%;display:block;background:var(--accent);transition:width .25s}.band i.second{background:var(--second)}button:disabled{cursor:default}.status{font-size:13px;min-height:4.8em}.mono{font-family:ui-monospace,monospace;font-variant-numeric:tabular-nums}.muted{color:var(--muted)}\n@media(max-width:480px){.two{gap:8px}.card{padding:12px 9px}.actions button,.presets button{font-size:12px}.metrics strong{font-size:20px}.metrics{gap:8px}}\n@media(prefers-reduced-motion:reduce){*,*::before,*::after{transition:none!important;animation:none!important}}\n.track-row{margin:16px 0}.track-row>span{display:block;font-size:12px;color:var(--muted);margin-bottom:7px}.track{display:flex;gap:5px;min-width:0}.cell{flex:1;min-width:0;min-height:48px;border:1px solid var(--rule);border-radius:5px;background:var(--surface);display:flex;align-items:center;justify-content:center;text-align:center;padding:5px 3px;font-size:12px;overflow-wrap:anywhere;font-variant-numeric:tabular-nums}.cell.on{background:var(--accent-soft);border-color:var(--accent)}.cell.gold{background:var(--second-soft);border-color:var(--second)}.cell.empty{border-style:dashed;color:var(--muted)}.cell.error{border-color:var(--second);text-decoration:line-through}.choices{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:6px;margin:14px 0}.choices button{min-width:0;padding:10px 4px;font-size:12px;overflow-wrap:anywhere}.choices button[aria-current=true]{border-color:var(--accent);background:var(--accent-soft)}.relation{display:grid;grid-template-columns:minmax(0,1fr) 28px minmax(0,1fr);align-items:center;gap:6px;margin:12px 0}.relation .cell{min-height:72px}.relation>i{text-align:center;font-style:normal;color:var(--accent)}.readout{font-size:13px;white-space:pre-line;min-height:6.4em;overflow-wrap:anywhere}.plot{position:relative;border-left:1px solid var(--rule);border-bottom:1px solid var(--rule);padding:8px 0;margin:18px 0}.plot-row{height:28px;position:relative;margin:4px 0;background:var(--surface)}.plot-row i{position:absolute;inset-block:5px;background:var(--accent);min-width:2px;transition:width .2s,left .2s}.plot-row b{position:relative;padding:4px 6px;font:11px/28px ui-monospace,monospace;background:var(--paper);border-radius:3px}.axis{display:flex;justify-content:space-between;font-size:11px;color:var(--muted)}\n\n/* Action labels must remain readable across locales and narrow embeds. */\n.actions{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:8px}\n.actions button{overflow-wrap:anywhere;white-space:normal;min-height:58px;padding:8px}\nbutton{overflow-wrap:anywhere}\n@media(min-width:640px){.actions{grid-template-columns:repeat(3,minmax(0,1fr))}}\n\n.metrics span{overflow-wrap:anywhere}\n.panel{border:1px solid var(--rule);border-radius:9px;padding:12px;margin:14px 0;min-width:0}.panel h3{font-size:13px;margin:0 0 10px;color:var(--muted)}.source{font:13px/1.8 ui-monospace,monospace;white-space:pre-wrap;overflow-wrap:anywhere;margin:12px 0}.source mark{background:var(--accent-soft);color:var(--ink);border-bottom:2px solid var(--accent)}.source .fault{background:var(--second-soft);border-color:var(--second)}.diagram{display:block;width:100%;height:auto;max-height:320px;margin:14px 0;overflow:visible}.diagram text{fill:var(--ink);font:12px ui-monospace,monospace}.diagram .edge{stroke:var(--muted);stroke-width:1.5;fill:none}.diagram .edge.on{stroke:var(--accent);stroke-width:3}.diagram .node{fill:var(--surface);stroke:var(--rule);stroke-width:1.5}.diagram .node.on{fill:var(--accent-soft);stroke:var(--accent)}.diagram .node.gold{fill:var(--second-soft);stroke:var(--second)}.log{font:12px/1.8 ui-monospace,monospace;white-space:pre-line;overflow-wrap:anywhere;min-height:7.2em}.table{display:grid;gap:5px;margin:14px 0}.table .tr{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:5px}.table .tr>*{padding:8px 5px;background:var(--surface);border-radius:4px;min-width:0;overflow-wrap:anywhere;font-size:12px}.table .tr .on{background:var(--accent-soft)}.table .tr .gold{background:var(--second-soft)}.choices button{min-height:44px}.metrics strong{min-height:1.6em}.code-line{display:block}.code-line.on{background:var(--accent-soft);border-left:2px solid var(--accent);padding-left:6px}.status-badge{font-size:12px;color:var(--accent)}.tile-grid{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:6px}.tile-grid .cell{min-height:40px}.actions button{min-height:48px}.form-field{display:grid;gap:8px;margin:14px 0;font-size:13px}.form-field input{width:100%;font-family:ui-monospace,monospace}.metrics.three{grid-template-columns:repeat(3,minmax(0,1fr))}.formula{min-height:3.2em}.presets{flex-wrap:wrap}.presets button{flex-basis:25%;min-height:44px}\n\n.budget{display:flex;height:28px;margin:16px 0;background:var(--surface);border-radius:5px;overflow:hidden}.budget i{display:block;background:var(--accent);transition:width .2s}.budget i.gold{background:var(--second)}.intervals{margin:16px 0}.interval{position:relative;height:36px;background:var(--surface);margin:6px 0;border-radius:4px;overflow:hidden}.interval i{position:absolute;height:100%;background:var(--accent-soft);border-left:2px solid var(--accent)}.interval i.gold{background:var(--second-soft);border-color:var(--second)}.interval span{position:relative;z-index:1;font:12px/36px ui-monospace,monospace;padding-left:7px}.table .tr>*{min-height:4.8em}.formula{white-space:pre-line;min-height:7.2em}.actions:has(>button:only-child){grid-template-columns:1fr}.metrics strong{min-height:3.2em}.rangegrid{display:grid;grid-template-columns:repeat(12,minmax(0,1fr));gap:3px;margin:14px 0}.rangegrid .cell{min-height:30px;padding:3px 1px;font-size:10px}.message{min-height:7.2em;white-space:pre-line;font:13px/1.8 ui-monospace,monospace;overflow-wrap:anywhere}\n/* Allow CJK hanging punctuation without overflowing a metric's border box. */\n.metrics>div{padding-right:4px}.metrics span{line-break:anywhere}\n\n.chart-wrap{margin:18px 0}.chart-label{font-size:12px;color:var(--muted);min-height:3.2em}.curve{display:block;width:100%;height:auto;max-height:320px;overflow:visible}.curve text{font:11px ui-monospace,monospace;fill:var(--muted)}.gridline{stroke:var(--rule);stroke-width:1}.metrics strong{font-size:20px;min-height:3.2em}.formula{font:12px/1.8 ui-monospace,monospace;min-height:9em}.readout{min-height:8em}.presets button{flex-basis:30%}.scope p{overflow-wrap:anywhere} .unit-note{font-size:12px;color:var(--muted);margin:10px 0}\n\n.metrics span{word-break:break-all;line-break:strict}.metrics>div{padding-right:6px}\n\n","js":"const $=s=>document.querySelector(s);const set=(id,v)=>$('#'+id).textContent=v;const t=k=>viz.t(k);function cells(id,values){$('#'+id).replaceChildren(...values.map(v=>{const e=document.createElement('div');e.className='cell '+(v.cls||'');e.textContent=v.text;e.title=v.title||v.text;return e;}));}function pressed(mode){document.querySelectorAll('[data-mode]').forEach(e=>e.setAttribute('aria-pressed',String(e.dataset.mode===mode)));}const esc=s=>String(s).replace(/[&<>\"']/g,c=>({'&':'&','<':'<','>':'>','\"':'"',\"'\":'''}[c]));const fmt=s=>'{'+[...s].sort().join(', ')+'}';function graph(id,nodes,edges){const el=$('#'+id);el.setAttribute('viewBox','0 0 360 200');el.innerHTML='<defs><marker id=\"arrow-'+id+'\" viewBox=\"0 0 10 10\" refX=\"8\" refY=\"5\" markerWidth=\"5\" markerHeight=\"5\" orient=\"auto-start-reverse\"><path d=\"M 0 0 L 10 5 L 0 10 z\" fill=\"var(--muted)\"/></marker></defs>'+edges.map(e=>{const a=nodes[e[0]],b=nodes[e[1]],dx=b.x-a.x,dy=b.y-a.y,d=Math.hypot(dx,dy)||1;if(edges.some(r=>r[0]===e[1]&&r[1]===e[0])){const nx=-dy/d,ny=dx/d;return '<path class=\"edge '+(e[2]?'on':'')+'\" d=\"M '+(a.x+dx/d*22+nx*12)+' '+(a.y+dy/d*22+ny*12)+' Q '+((a.x+b.x)/2+nx*38)+' '+((a.y+b.y)/2+ny*38)+' '+(b.x-dx/d*25+nx*12)+' '+(b.y-dy/d*25+ny*12)+'\" marker-end=\"url(#arrow-'+id+')\"/>';}return '<line class=\"edge '+(e[2]?'on':'')+'\" x1=\"'+(a.x+dx/d*25)+'\" y1=\"'+(a.y+dy/d*25)+'\" x2=\"'+(b.x-dx/d*28)+'\" y2=\"'+(b.y-dy/d*28)+'\" marker-end=\"url(#arrow-'+id+')\"/>';}).join('')+nodes.map(n=>'<g><circle class=\"node '+(n.cls||'')+'\" cx=\"'+n.x+'\" cy=\"'+n.y+'\" r=\"25\"/><text x=\"'+n.x+'\" y=\"'+(n.y+4)+'\" text-anchor=\"middle\">'+esc(n.name)+'</text>'+(n.sub?'<text x=\"'+n.x+'\" y=\"'+(n.y+43)+'\" text-anchor=\"middle\">'+esc(n.sub)+'</text>':'')+'</g>').join('');}function table(id,rows){$('#'+id).classList.add('table');$('#'+id).replaceChildren(...rows.map(r=>{const row=document.createElement('div');row.className='tr';row.style.gridTemplateColumns='repeat('+r.length+',minmax(0,1fr))';r.forEach(x=>{const c=document.createElement('div');if(typeof x==='object'){c.textContent=x.text;c.className=x.cls||'';}else c.textContent=x;row.append(c)});return row;}));}function band(id,parts,total){$('#'+id).replaceChildren(...parts.map((p,i)=>{const e=document.createElement('i');e.style.width=(100*p.value/total)+'%';e.className=i%2?'gold':'on';e.title=p.name+': '+p.value;return e}));}function intervals(id,items,total){$('#'+id).replaceChildren(...items.map(p=>{const row=document.createElement('div');row.className='interval';const bar=document.createElement('i');bar.style.left=(100*p.start/total)+'%';bar.style.width=(100*(p.end-p.start)/total)+'%';bar.className=p.cls||'';const label=document.createElement('span');label.textContent=p.label;row.append(bar,label);return row;}));}function plot(id,series,xr,yr,opts={}){const e=$('#'+id),X=x=>42+(x-xr[0])/(xr[1]-xr[0])*298,Y=y=>175-(y-yr[0])/(yr[1]-yr[0])*148;let out='<defs><clipPath id=\"clip-'+id+'\"><rect x=\"42\" y=\"27\" width=\"298\" height=\"148\"/></clipPath></defs>';for(let i=0;i<3;i++){let x=xr[0]+i*(xr[1]-xr[0])/2,y=yr[0]+i*(yr[1]-yr[0])/2;out+='<path class=\"gridline\" d=\"M '+X(x)+' 27V175M42 '+Y(y)+'H340\"/><text x=\"'+X(x)+'\" y=\"194\" text-anchor=\"middle\">'+esc(opts.xfmt?opts.xfmt(x):Number(x.toFixed(2)))+'</text><text x=\"36\" y=\"'+(Y(y)+4)+'\" text-anchor=\"end\">'+esc(opts.yfmt?opts.yfmt(y):Number(y.toFixed(2)))+'</text>';}out+='<g clip-path=\"url(#clip-'+id+')\">';for(const s of series){out+='<path fill=\"none\" stroke=\"'+(s.color||'var(--accent)')+'\" stroke-width=\"2.5\" '+(s.dash?'stroke-dasharray=\"5 4\"':'')+' d=\"'+s.pts.map((p,i)=>(i?'L':'M')+X(p[0]).toFixed(2)+','+Y(p[1]).toFixed(2)).join(' ')+'\"/>';}for(const p of opts.points||[])out+='<circle cx=\"'+X(p[0])+'\" cy=\"'+Y(p[1])+'\" r=\"4\" fill=\"var(--second)\" stroke=\"var(--paper)\" stroke-width=\"1.5\"/>';if(opts.cursor!==undefined)out+='<path d=\"M'+X(opts.cursor)+' 27V175\" stroke=\"var(--muted)\" stroke-dasharray=\"3 3\"/>';e.innerHTML=out+'</g>';e.dataset.curves=JSON.stringify(series.map(s=>s.pts));}const curve=(fn,lo,hi,n=120)=>Array.from({length:n+1},(_,i)=>{const x=lo+(hi-lo)*i/n;return[x,fn(x)]});function inputs(draw){document.querySelectorAll('input,select').forEach(e=>{e.addEventListener('input',draw);e.addEventListener('change',draw)});draw()}const n=id=>+$('#'+id).value;const show=(id,v,d=3)=>set(id,Number(v.toFixed(d)));function draw(){let count=n('count'),rtt=n('rtt'),cap=16*128/130*4/8,rate=x=>Math.min(cap,x*256/rtt/1000);show('count-value',count);show('rtt-value',rtt);plot('plot',[{pts:curve(rate,0,128)},{pts:[[0,cap],[128,cap]],dash:true,color:'var(--second)'}],[0,128],[0,9],{points:[[count,rate(count)]]});show('window',count*256);show('rate',rate(count),4);show('needed',Math.ceil(cap*1000*rtt/256));set('eq','Bwindow = N × 256 B\\nR ≤ min(7.877, Bwindow/RTT) GB/s\\nNneeded = ceil(Clink × RTT / 256 B)');}inputs(draw);","audio":false,"strings":{"count":"未完了要求上限","heading":"リンクが空いていてもデータを待つ理由は?","intro":"未完了要求数と往復遅延を変え、窓とリンクの上限を比較。","needed":"リンクを満たす最少要求数","plot":"横軸 要求数、縦軸 GB/s、破線:リンク上限","rate":"予算上限(GB/s)","reset":"リセット","rtt":"往復時間(μs)","scope":"Gen4×4符号化後7.877 GB/s、要求256 B、平均RTT固定。TLP・クレジット・メモリ・素子の追加負担は省略。","scopeLabel":"モデルの範囲と前提","window":"未完了バイト(B)"}}
電源投入からドライバ使用まで:トレーニングと列挙は2段階で理解する
物理リンクは受信検出、トレーニングシーケンス、幅/レートの確立、および対応するイコライゼーションを経て利用可能な状態に入ります。これらの状態遷移は LTSSM で記述されることが多いです。両端の最高能力、配線、ファームウェアポリシー、および信号品質が最終結果を決定し、より狭い幅やより低いレートに降下する可能性があります。リカバリ状態は再トレーニングにも使用されます。
その後、ファームウェア/OS は設定スペースを通じてデバイスとブリッジを検出し、バス番号とリソースウィンドウを割り当てます。BAR はデバイスが必要とするアドレス空間の領域を記述し、ホストがアドレスを割り当てた後に、ドライバがマッピングし、デバイスの規則に従って MMIO にアクセスできます。BAR は通常のメモリスティックではなく、物理デバイスを「RAM にコピーする」ものでもありません。
デバイスが DMA を実行するには、バスマスター能力、正しいマッピング、IOMMU の権限、およびドライバの同期が必要です。リンクが L0 にあり、lspci でデバイスがリストされていても、データ転送が行われない場合は、ドライバ、リソース、または DMA の設定に問題がある可能性があり、必ずしもスロットの交換が必要というわけではありません。IOMMU と DMA API
物理設計は単一の等しい数字の羅列だけを暗記してはいけない
PCIe シリアル受信は CDR を介してデータからタイミングを復元しますが、多くのプラットフォームでは参照クロックを提供し続けています。「クロック埋め込み」は、基板に REFCLK がないことを意味しません。Common Clock、SRNS、SRIS は異なる参照方式であり、両端の能力と SSC 設定と一致させる必要があり、現在すべてが SRIS を採用していると断言することはできません。Intel:SRIS の適用背景
交流結合は通常、送信パスに合わせて配置され、各方向に対応する送信端があります。リンクの両端に機械的にキャパシタセットを追加しないでください。キャパシタ値、位置、差動インピーダンス、損失、ビアスタブ、および長さのばらつきの要件は、目標仕様、パッケージ、およびベンダーの配線ガイドラインに基づいて決定する必要があります。内部スキューとレーン間スキューは異なる制約であり、「すべての P/N は 5 mil 未満でなければならない」と一律に書くのは条件が不足しており、より重要な損失予算を隠蔽します。
Redriver は主にアナログ信号の損失を補償し、Retimer はさらにクロック/データ復元と再送信を行います。両者は消費電力、レイテンシ、互換性、およびトレーニングサポートが異なり、アンプを1つ追加するだけでリンクを無限に延長できるとは考えられません。継続的なリターンプレーン、リターンパス、およびコネクタの遷移が基本です。
NVMe、ReBAR、CXL はそれぞれ PCIe 上に何を追加するのか
NVMe はストレージコマンドとキューモデルであり、PCIe は一般的なローカル転送基盤の一つです。NVMe over Fabrics では、他のネットワーク転送も使用できます。マルチキューにより、異なる送信者が競合を減らし、並行性を維持できますが、仕様で表現できるキュー数/深さが、各コントローラが上限を実装していることを意味するわけではありません。ディスク読み込みはビジネスセマンティクス上「読み込み」ですが、コントローラがデータをホスト RAM に送信する際には通常 PCIe Memory Write を送信するため、ビジネス方向とトランザクションタイプを混同してはいけません。Intel:I/O データフローの例
Resizable BAR は、デバイスがサポートするサイズから BAR ウィンドウを選択できるようにします。より大きなウィンドウは、VRAM ウィンドウの再マッピングなどのオーバーヘッドを削減する可能性があります。256 MiB は一部の古い GPU の一般的なウィンドウサイズですが、すべての PCIe BAR の統一された上限ではありません。ReBAR はレーン帯域幅を自動的に向上させるわけでも、すべてのコピーを削減する保証もありません。ファームウェアアドレススペース、GPU、ドライバ、およびアプリケーションが、利用可能性と収益を共同で決定します。PCI-SIG:Resizable BAR
CXL は PCIe の物理基盤を利用し、CXL.io、CXL.cache、CXL.mem などのプロトコルセマンティクスを追加し、一貫性とメモリアクセスのシナリオに役立てます。通常の PCIe デバイスは、類似のスロットに挿入しただけでは CXL メモリデバイスにはなりません。ホスト、デバイス、ファームウェア、およびソフトウェアの対応するサポートが必要です。CXL アライアンス:プロトコルと一貫性の位置づけ
GPU のワークロードが PCIe に敏感な程度は、データが VRAM に長期間滞在するかどうか、頻繁に交換されるかどうか、VRAM の容量と同期方法に依存します。「x8 に固定すると 1%~3% の損失」といった一般的な結論を排除し、GPU シリーズ名から予測するのではなく、実際のワークセットを測定する必要があります。
Linux ではまず現在のリンクを見てから、最大能力を見る
lspci - t
lspci - nn
lspci - s 0000:01:00.0 - vv
LnkCap(能力)と LnkSta(現在の速度/幅)に注目し、ブリッジおよびルートポートを上にたどって確認する。設定スペースの読み取りは権限制限の影響を受けるため、出力が不完全になる可能性がある。Linux PCI sysfs には、current_link_speed、current_link_width、max_link_speed、max_link_width などの読み取り専用属性も提供されているが、すべてのデバイスや設定で全フィールドが存在するわけではない。フィールドと単位は Linux PCI sysfs ABI で確認できます。
1回のアイドル時のサンプリングで負荷状態を断定しないでください。デバイスは動的にレートを下げて省電力化する可能性があり、リンクの異常が実際にデグラデーションを引き起こしている可能性もあります。負荷、AER ログ、およびパストポロジと組み合わせて分析する必要があります。ここでは読み取り方法のみを示しており、リンク制御の変更、再トレーニング、またはリソースレジスタについては言及していません。
符号化と在途ウィンドウの再計算
from fractions import Fraction as F
per_lane = F ( 16_000_000_000 ) * F ( 128 , 130 ) / 8
x4 = per_lane * 4
assert x4 == F ( 102_400_000_000 , 13 )
assert float ( x4 ) / 1e9 < 8
assert 2 * 5e9 > x4
window_bytes = 32 * 256
window_rate = F ( window_bytes ) / F ( 2 , 1_000_000 )
assert window_rate == 4_096_000_000
assert window_rate < x4
needed = x4 * F ( 2 , 1_000_000 )
assert needed > window_bytes
print ( ' Gen 4×4 符号化後単方向上限:' , round ( float ( x4 ) / 1e9 , 6 ) , ' GB/s' )
print ( ' 32 筆 256 B、2 μs 往復のウィンドウ上限:' , float ( window_rate ) / 1e9 , ' GB/s' )
上記は明確な仮定に基づく予算の検証のみを行い、実際の GPU、SSD、または PCIe スループットのテストは行っていません。
さらに参照する