NUMA と Cache の関係

NUMAの基本形は、この様な形でCPU1とCPU2のそれぞれに接続されたメモリに対するアクセスコスト(レイテンシや帯域)がインターネコクトを経由するかしないかで異なるという話で、AMD K8 初期の SledgeHammerコアがこれに該当しますが、
NUMA-Z.png

これとは別の問題としてCPUの内部構造に依存した問題があります。

例えば、Core2QuadやXEON 54xx/53xxは構造的にL2キャッシュがこんな感じになっています。
C2QCACHE.png
この図で左側のL2キャッシュにあるデータにアクセスする場合、Core1とCore2はオンキャッシュで高速なアクセスが出来ますが、Core3とCore4が同じデータにアクセスするにはキャッシュコヒーレンシを維持しつつMCH経由でDRAMにアクセスしなければならず、アクセスコストはCore1/2とCore3/4で異なります。

Sandy以降のリングバスを使ったモデルでは複雑です。
SANDYCACHE.png
全コアでメインメモリ間の帯域は同等ですが、リングバスの特徴として遠距離になるとレイテンシが増えますから、この図ではCore1やCore5は常にメモリレイテンシがCore4やCore8より多くなってしまうはずです。

加えて、HyperThreadが使える為、論理コアはLLCを共有していますから論理的には上のCore2Quadの様な構造を内包しています。

Haswell-EPの大規模コアは更に複雑で、CPUダイ上にNUMA的な構造があり、論理構造上は下図でいうとCore12だけ左側のドメインに属し、る左右とも9コアで対称構造ですが物理構造的には見ての通り右側がヘビーな感じの変則的な構成です。
HASEPCACHE.png


これが、デュアルソケットやマルチソケットに成ると、アクセスコストはカオスですね。
HASEPCACHED.png

OSのスケジューラがCPUの性能を引き出すには、これを把握し、発熱を配慮して、メモリ配置やスレッド負荷の割り振りをしなければなりません。

アプリをチューニングする際にも同じ事が言えそうですね。

CPUコア <-> LLC が最速ですが、他のアクセスコストのパターンとして

CPUコア <-> LLC <-> リング <-> 隣のLLC
CPUコア <-> LLC <-> リング <-> DRAM
CPUコア <-> LLC <-> リング <-> SW <-> リング <-> 隣のLLC
CPUコア <-> LLC <-> リング <-> SW <-> リング <-> DRAM
CPUコア <-> LLC <-> リング <-> QPI <-> リング <-> DRAM
CPUコア <-> LLC <-> リング <-> SW <-> リング <-> QPI <-> リング <-> DRAM
CPUコア <-> LLC <-> リング <-> SW <-> リング <-> QPI <-> リング <-> SW <-> リング <-> DRAM


と、これだけのパターンが有ると思いますし、それぞれ、レイテンシが異なると思われます。
SWAPの事は一緒に考えたくないですが、登場間際のDIMMスロットに挿せるタイプのSSDを混載した場合には考慮する事になるのでしょうね。

ソフト的にこれらを感知する方法は、UEFI/BIOSで設定されているACPIのSRAT(2.0)/SLIT(3.0)/MSCT(4.0)などが基本に有り、BIOS/UEFI上の設定状況を参照するにはRW utilityを使うと簡単に確認出来ます。

OSがこれをどう認識しているかは、WindowsではCoreinfoで確認出来ます(但し、OSはACPIの情報を100%利用している訳ではない様です)。Linuxではどうやって確認するか?未調査ですが、オープンソース故に自分でチューニング出来る楽しみがありそうですね。

定数として利用されるReadOnly属性のメモリ空間はコヒーレンシ維持コストが削減出来そうですが、それを考慮したプログラミングがどこまでされているか筆者は存じません。

以下はソケットG34デュアルの最小構成になるAbuDahbiコアのローエンド品 Opteron 6308 を2基搭載したシステムでCorinfoを実行した結果ですが、途中にありますアクセスコストは概ね出鱈目に近い状況です。モジュール構造はHyperThreadとして認識されている事が判ります。未調査ですがLinuxのカーネルAPIやスケジューラがどうなっているのか興味が有りますね!?

Logical to Physical Processor Map:
**------ Physical Processor 0 (Hyperthreaded)
--**---- Physical Processor 1 (Hyperthreaded)
----**-- Physical Processor 2 (Hyperthreaded)
------** Physical Processor 3 (Hyperthreaded)

Logical Processor to Socket Map:
****---- Socket 0
----**** Socket 1

Logical Processor to NUMA Node Map:
**------ NUMA Node 0
--**---- NUMA Node 1
----**-- NUMA Node 2
------** NUMA Node 3

Approximate Cross-NUMA Node Access Cost (relative to fastest):
00 01 02 03
00: 1.0 1.4 1.8 1.5
01: 1.8 1.4 1.9 2.0
02: 2.0 1.9 1.4 2.0
03: 1.9 2.0 1.9 1.3

Logical Processor to Cache Map:
*------- Data Cache 0, Level 1, 16 KB, Assoc 4, LineSize 64
*------- Instruction Cache 0, Level 1, 64 KB, Assoc 2, LineSize 64
*------- Unified Cache 0, Level 2, 2 MB, Assoc 16, LineSize 64
-*------ Data Cache 1, Level 1, 16 KB, Assoc 4, LineSize 64
-*------ Instruction Cache 1, Level 1, 64 KB, Assoc 2, LineSize 64
-*------ Unified Cache 1, Level 2, 2 MB, Assoc 16, LineSize 64
**------ Unified Cache 2, Level 3, 12 MB, Assoc 1, LineSize 64
--*----- Data Cache 2, Level 1, 16 KB, Assoc 4, LineSize 64
--*----- Instruction Cache 2, Level 1, 64 KB, Assoc 2, LineSize 64
--*----- Unified Cache 3, Level 2, 2 MB, Assoc 16, LineSize 64
---*---- Data Cache 3, Level 1, 16 KB, Assoc 4, LineSize 64
---*---- Instruction Cache 3, Level 1, 64 KB, Assoc 2, LineSize 64
---*---- Unified Cache 4, Level 2, 2 MB, Assoc 16, LineSize 64
--**---- Unified Cache 5, Level 3, 12 MB, Assoc 1, LineSize 64
----*--- Data Cache 4, Level 1, 16 KB, Assoc 4, LineSize 64
----*--- Instruction Cache 4, Level 1, 64 KB, Assoc 2, LineSize 64
----*--- Unified Cache 6, Level 2, 2 MB, Assoc 16, LineSize 64
-----*-- Data Cache 5, Level 1, 16 KB, Assoc 4, LineSize 64
-----*-- Instruction Cache 5, Level 1, 64 KB, Assoc 2, LineSize 64
-----*-- Unified Cache 7, Level 2, 2 MB, Assoc 16, LineSize 64
----**-- Unified Cache 8, Level 3, 12 MB, Assoc 1, LineSize 64
------*- Data Cache 6, Level 1, 16 KB, Assoc 4, LineSize 64
------*- Instruction Cache 6, Level 1, 64 KB, Assoc 2, LineSize 64
------*- Unified Cache 9, Level 2, 2 MB, Assoc 16, LineSize 64
-------* Data Cache 7, Level 1, 16 KB, Assoc 4, LineSize 64
-------* Instruction Cache 7, Level 1, 64 KB, Assoc 2, LineSize 64
-------* Unified Cache 10, Level 2, 2 MB, Assoc 16, LineSize 64
------** Unified Cache 11, Level 3, 12 MB, Assoc 1, LineSize 64

Logical Processor to Group Map:
******** Group 0
 
スポンサーサイト

Dual Socket な PC の割り込みに付いて

 今回は、PCの割り込み(Interrupt)処理に付いて、基本的な所から Dual Socket での割り込み処理までを簡単にまとめてみます。(基本的には自分用メモで、現在編集中です)

 筆者の知る割り込み処理には大きく分けて3タイプ(ソフト割り込み、ハード割り込み、NMI(強制割り込み))が有りますが、今回の記事の対象はI/Oデバイスのハード割り込みに付いてです。余談ですがソフト割り込みは例外処理とも言われ代表的なものにNullPointerExceptionなどが有ります。

 発端は 先日の記事 です。
 例えば下図の様なNUMA構成でCPU1で動作しているアプリがCPU2のI/Oバスに接続されたデバイスを利用する場合、割り込みの経路やドライバとの関係に付いて詳しく調べようと思った訳です。
NUMA-Z.png

 ハード割り込みは、主にデバイスの状態通知(データ転送完了通知など)やデバイスへの要求通知(データ転送要求など)をソフトウエア(OS)との間で行う手段として利用されます。その為、割り込み処理を行うのは主にデバイスドライバという事に成り、その骨格(フレームワーク)はOSが担っています。デバイスドライバはISR(Interrupt Service Routine)によって割り込み要求を受け取ったCPUコアで実行・処理されます。

デバイスドライバとCPUコアの紐付け
 ※英語ではAffinity(又はBind)と言いますがMSはAffinityを「関係」と意訳している様です。筆者は「紐付け」と意訳してみました。
 先日の記事で紹介しました Interrupt Affinity Policy ツール(Vista以降) 又は Interrupt affinity filter ツール(Win2000以降)(FTPサイトがリンク切れでDownLoad出来ない場合は[MD5:3CC85F0DDDD44865D8469C2E75500A97]と合致するIntFiltr.zipファイルをネット上で探して下さい)は、主にマルチソケット環境でチューニングをする際に利用するツールですが、シングルソケットであっても 「デバイス-A で発生した割り込みを CPUコア-B に処理させる」といった設定が出来ますので、チューニングを行う際には活用できそうです。例えばマルチコアCPUではキャッシュを共有するコアと共有しないコアが有ったりしますので、極力キャッシュを共有するコアに目的のアプリとデバイスドライバを集約する事で高速化するケースが有ります。CPU負荷自体がそれほど高くない場合は単独のコアに目的のアプリとデバイスドライバを集約してL1を共有させた方が早くなる事もあります(CPU負荷が高い場合は逆効果に成ります)。但し、IRQを他のデバイスと共有している場合は紐付け設定が出来ませんのでIRQをデバイスと一対一に対応付ける事が前提に成ります。
 キャッシュとCPUコアの関係はCoreinfo -lで確認出来ます。
 紐付けの具体的な方法は先日の記事でUSB3.0を例に解説しております。このケースではチューニングの効果で30%以上の高速化に成功しています。

 アプリとCPUコアの紐付けはStartコマンド(Vista以降)又はIMAGECFG.EXE(NT4.0~XPの32Bitアプリ専用)で行います。
 Vista/2008でのコマンドライン
  C:\Start /AFFINITY [CPUコア@16進数] [アプリ]
 Win7/2008R2でのコマンドライン
  C:\Start /NODE [NUMA-node] /AFFINITY [CPUコア@16進数] [アプリ]

 Win2003-64Bit及びXP-64Bitではタスクマネージャで「関係の設定」を行う以外にアプリとCPUを紐付ける方法が無さそうです。但しIMAGECFG.EXEはEXEバイナリ自体を変更する為、NT4.0~XP世代のOS向けにコンパイルされた32BitアプリはIMAGECFG.EXEで恒久的な紐付け設定が出来ます。それをVista/7や64Bit-OSで実行した場合には紐付けが有効です。逆に言うとIMAGECFG.EXEは64BitバイナリやNT6.0以降の32Bitバイナリに対応していません。対応していない64BitやVista以降のEXEバイナリに対してIMAGECFG.EXEを実行してしまうと起動不可なゴミバイナリに成ってしまうので要注意です。IMAGECFG.EXEを使う場合はアプリ本体ではなくコピーしたテスト用EXEファイルで試してからにして下さい。という事で、調査しつつIMAGECFG.EXEと同様の機能で64BitやVista以降のバイナリに対応可能なツールを製作してみとうかと思っています(協力頂ける方は連絡下さい)。余談ですがIMAGECFG.EXEはマルチコアに未対応の古いアプリを恒久的にマルチコア環境でも実行可能なバイナリに改造するツールとも言えそうです。

以下、話を割り込みに戻します・・・

PC/AT互換機の標準的なIRQ
 IRQ 00 システムタイマ
 IRQ 01 PS/2 キーボード
 IRQ 02 IRQ 09へのカスケード接続/古いPCではISAデバイスが利用
 IRQ 03 シリアルポート2(COM2/COM4)
 IRQ 04 シリアルポート1(COM1/COM3)
 IRQ 05 プリンタ(LPT2)/オーディオ・サウンド
 IRQ 06 Floppy controller
 IRQ 07 プリンタ(LPT1)
 IRQ 08 リアルタイムクロック
 IRQ 09 IRQ2へのリダイレクト(兼 APIC SCI)
 IRQ 10
 IRQ 11

 IRQ 12 PS/2 マウス
 IRQ 13 数値データプロセッサ(8087コプロセッサ互換)
 IRQ 14 ATA Channel 0 / IDE Primary
 IRQ 15 ATA Channel 1 / IDE Secondary
 IRQ 16APIC搭載システムとWindowsNT系OSの組み合わせで利用可
 IRQ -2MSI搭載システムとWindowsVista以降のOSで利用可

 赤字のIRQは基本的には変更不可です。
 緑字で示したIRQはPC/ATとの互換性を保ったままPCIカードに割り当て可能です。
 青字のIRQはCOMやLPTなどのPC/AT標準デバイスを無効にする事で互換性を大きくは崩さずに他のデバイスに割り当て出来る可能性が高いのですがBIOSやFirmwareやチップセット次第でもあり、古いソフトではデバイスが存在しなくても固定的に利用しているものもあり誤動作の可能性が有ります。
 IRQ 02 と IRQ 09 はカスケード接続なので、どちらか片方を利用する場合、もう一方は利用出来ません。IRQ 02 は古いISAカードで固定的に利用されていた経緯から古いPCでは予約的な位置づけで利用される事が有る様で、この場合は IRQ 09 が利用出来ません。逆にAPIC世代では SCI (System Control Interrupt) に利用されますので IRQ 02 が利用出来ません。
 橙色のIRQはPC/ATとの下位互換は無く、後に追加されたAPICやMSIの導入で拡張されたIRQです。従いましてAPICやMSIに未対応のマザーやOSやドライバでは利用出来ません。

PIC(Programmable Interrupt Controllers)
 IBM PC/ATに搭載されていた割り込みコントローラです。PICを使ったシステムでは上記のIRQ15までしか利用出来ません。

APIC(Advanced Programmable Interrupt Controllers)
 APIC(ACPIとスペルが似ていて間違いやすいですが別物です)は古くはSocket7のDUAL SOCKETシステムにチップセットの1つとして搭載され、ハード的な割り込み制御の要(かなめ)を担っています。それ以降のDualSocketマザーには概ねAPIC互換機能が搭載され続け、マルチコアが一般的に成った現在ではほぼ全てのPC用マザーにAPIC互換機能が搭載されAPICはハード割り込みの中核的存在に成っています。
 PC/ATの完全互換を目指す場合はAPICではなくPIC(Programmable Interrupt Controllers)になりますがPICには複数CPUに対応する機能が不足していた為にAPICが導入された経緯が有り、DualSocketのみならずDualCore以上のCPUではAPICが必須になります。但しAPICを搭載したシステムでも下位互換目的でBIOS/UEFIやジャンパでAPICとPICを切り替え可能なマザーもあります。
 IBM PC/ATに搭載されていたPICではIRQ15までにしか対応していませんでしたのでIRQシェアリング/IRQステアリングの様な機能が追加され複数デバイスでIRQを共有しているシステムも有ります。対してAPICを搭載したシステムではIRQ 16以上を個々のデバイスに個別に割り当て可能に成りました。但し、APICを搭載していてもチップセットの制限や回路を省略した結果IRQを共有していたり、複数CPUに対応していないWindows9x/Meの時代にはAPICを搭載しながらも互換性維持や回路を省略した為IRQ 15までしか利用出来ないマザーもあり、OSやドライバが未対応だった為にデバッグが進まずAPIC関連のBIOSにバグが存在する事が多い様です。
 下のスクリーンショットはAPICを搭載した430HXチップセットのSocket7マザーGIGABYTE GA-586DX Rev.3BのIRQです。
ResourceGA586DX_IRQ.png
 この様に1997年の古いマザーボードでもAPICを搭載しているものはIRQ 16以上の割り当てが可能で、個々のデバイスに対して個別のIRQを設定出来ます。

xAPIC(Extended APIC)
 Netburst世代(Pentium4)以降のAPIC実装。専用の4Bit APICバスを廃止しFSBに統合したもの。FSBと統合した事に伴い、もっさりの原因ではないか?と言われる事も有ります。名称はExtendedですが、実質的にはバス統一に伴うマザーボードの製造コスト削減と思われ、ソフトウエア面では互換性を維持していますが Low Priority Mode が機能削除されている様でます。

x2APIC(Extended APIC)
 Nehalem世代(Core i7/5/3)以降のAPIC実装。64Bit化に伴い20億個(40億とも)までの超並列CPUまで対応。
 未対応OS向けの設定としてBIOS/UEFIにてx2APICとxAPICの切り替えが出来るものが多い。

ACPI(Advanced Configuration and Power Interface Specification)
 APICの次にあえて名前の似ているACPIを持ってきました。
 MSのHPに詳しい記載が有ります。
 ACPI = 電源管理だと誤解されがちですが(筆者も最近まで誤解していましたが)名前の通り「構成と電源I/F」に付いて規定された規格でThe ACPI Specificationとして公開されています。
 ACPIでは様々なハードウエアの構成や設定をBIOS/UEFIからOSへ通知するテーブルが有り、電源のみならず全てのハードウエア構成や設定に関与していて、割込みに付いても例外ではありません。
 ACPIテーブルの中には先述のAPICに関する情報も含まれていてRW utilityで確認する事が出来ます。特にNUMAでのACPIに付いては別の記事で書いていますので参考にして下さい。

NUMAシステムにおける割り込み
 NUMA以前の(SMP/UMA)システムでは、1つのIO-APICと、個々のCPUコア内に有る複数のLocal-APICが共同して割り込みをハード的に処理していましたが、NUMAではNUMA-node毎にIO-APICが存在し個々のNUMA-nodeが同時並列的に処理している様です。実際、筆者所有のNUMA機にはIO-APICが2個搭載されている事が確認出来ました。確認方法はRW utilityを使ってACPIテーブル群の中にあるAPICテーブルを見ると判ります。
 OSはNUMA-node毎に発生する割り込みをリダイレクトする事で別のNUMA-nodeに対してISR(Interrupt Service Routine)とデバイスドライバを実行させる事が出来る様に成っている様です。冒頭の Interrupt Affinity Policy ツール等で物理的な接続状態に関わらず割り込みを処理させるNUMA-nodeやCPUコアを任意に設定可能です。

バス規格と割り込みに付いて
 ハード割り込みの仕組みは、バス規格毎に方式が異なりますが、今回はPCIとPCI-Expressに付いて主に扱い、後ほどISAに付いて追記するかもしれません。

PCI Rev2.1:
 PCIバスには INT A# ~ INT D# の4本の信号線が有り、バス本体とは非同期に割り込み信号の伝達が可能です。これは上位互換の64Bit-PCIや、更に上位のPCI-Xでも同じです。また派生規格のAGPも基本的には同じINT線形式ですがAGPの場合はINT A#のみのマザーやINT A#とINT B#しか無いケースが多い様です。(AGPは基本的にはGPUのみの単機能ですが、ATI ALL-IN-WONDER の様にキャプチャ機能やIEEE1394を搭載している物や、ATI Radeon HDの様に音源も内蔵した多機能AGPカードも実在します)
 このINT A# ~ INT D#がBIOSやPnPによってIRQを割り当てられ、その情報がESCD(Extended System Configuration Data)に格納されBIOSのいわゆるCMOSやNVRAMと言われるボタン電池で保護された不揮発メモリ領域に保存されます。従いましてESCDに不備が有るとIRQの衝突が起きたり、正常動作しなかったりしますのでボタン電池を交換したり、CMOSクリアをしたりする訳です(ESCDとACPIの関係に付いては調査中です)。
 この世代のAPICを搭載していない(つまりPICを搭載した)一般的なPC/AT互換機のINT結線は下図の様な状況で、AGPとPCI Slot1や、PCI Slot4と5が同じINT A#を共有する為、IRQの衝突が起き易い構造に成っています。(これは一例であって異なる場合があります)
PCIINTIRQ.png
 Onbord NIC INT B#
 OnBord USB INT C#
 OnBord Audio INT D#

 INT A# -> IRQ 11
 INT B# -> IRQ 10
 INT C# -> IRQ 09
 INT D# -> IRQ 05

 単機能のPCIカードはINT A#のみ利用する物が主流でIRQの衝突が起き難いのですが、複数の機能を搭載したマルチファンクションなコンボカードではINT A# ~ INT D#を機能数と同数またはそれ以上に利用する物が有ります。例えばUSB2.0/IEEE1394コンボカード等です。こういったマルチファンクションカードは他のPCIスロットのINT A#と同じINT線を利用する為、IRQの衝突が起き易くなります。
 PCI規格ではINT A# ~ INT D#の信号線を他のPCIカードと共有しない様に結線する事も出来ますがPC/AT互換機では互換性を保つ目的に加えコスト削減目的もあり、上図の様に全てのPCIスロットでINT線を共有しているのが一般的でした。但しDual Socketのシステムでは、先述のAPICを導入して個々のスロットに個別に結線しているものや64Bit-PCIやPCI-Xなどの別系統のI/Oバスが有りINT線を共有しない或いは部分共有のシステムが多々あります。
 INT線にどのIRQを設定可能かはBIOS及びチップセットで決まります。INT線を共有するPCIデバイス同士は必然的にIRQも共有します。逆にチップセットやBIOSの制限でINT線は共有していなくてもIRQを共有する場合があります。例えば互換性を最重視してPCIカードにはIRQ 10と11しか割り当て出来ないマザーも有ります。
 INT線及びIRQを共有する為の仕組みとしてIRQシェアリング/IRQステアリングが有りますが、全てのデバイスのハード/Firmware/デバイスドライバが規格に則り正しく対応しているとは限らず、また、頻繁な割り込みを必要とするデバイスでは規格通り製作されていても性能面でINTやIRQを共有することが難しいケースも有り得ます。特に映像や音楽などのリアルタイム性やシンクロ率を極限まで追求するデバイスでは結構シビアな問題と思われます。

PCI Rev2.2以降:
 PCI Rev2.2からは、以前のINT方式に加えてMSI(Message Signaled Interrupt)も導入されましたが、この世代のPC/AT互換機は基本的に前世代を踏襲しています。

 MSI(Message Signaled Interrupt)
 MSIはINT A#~D#を利用しない新しいタイプの割り込み方式で、MSIではIRQがマイナス値に成り構造的にIRQ競合が発生しない仕組みに成っています。INT線を使わない新しいタイプではありますが割り込みの伝達にAPICを利用する点では以前の割込み処理と共通しています。
 MSIは元々は主にSUN Microsystem社のSolaris向けデバイスにフォーカスして考案された仕組みの様でPC/AT互換機とは別の流れで発生した様です。筆者が利用していた頃のSUN SPARCstationはSBusカードでしたが、後に製造コスト面からPCIに切り替えた経緯が有り、その際にPCI Rev2.2で新たに策定された様です。
 MSIはINT A#~D#を利用せずIRQの競合が起きませんが、発生の経緯や互換性の問題からPC/AT互換機では当初は利用されていませんでした。従いましてPCI Rev2.2以降のデバイスに必ずMSIが搭載されている訳ではなく規格上も必須ではない様です。加えてWindowsでMSIを利用出来るのはVista/2008以降ですから、例えばWindowsXPやMSI未対応のPCI/PCI-ExpressカードはINTやINTx emulationで処理され、IRQ競合が起きるケースが有ります。
 MSIが搭載されているデバイスの場合Windows Vista以降のデバイスマネージャで確認するとIRQがマイナス値に設定されていますのでMSI搭載デバイス(かつMSIが利用できるシステム)かどうかの判断に利用出来ます。下のスクリーンショットの例ではRenesas製のUSB3.0がMSI対応している事が判ります。
 IRQ_NO15_2.png
 PC/AT互換機では、電源投入からPOST(Power on self test)が終了するまでは下位互換の為にINTで処理され、Vista/2008以降のOSでは起動過程でMSIに切り替わるのではないかと思われます(調査中・要確認)

PCI Rev3.0以降:
 PCI Rev3.0からは、以前の方法に加えてMSIを拡張したMSI-X(Extended Message Signaled Interrupt)も導入されましたが、この世代は既に主流がPCI-Expressに移行しつつある過渡期です。

 MSI-X(Extended Message Signaled Interrupt)
 MSI-Xは名前の通りMSIを拡張したもので、Windowsでは大きく別けて2種類の拡張が有る様です。

 1:ネットワークのポート単位でCPUコアの割り当てが可能
 2:デバイスに近いNUMA-nodeを自動選択して割り込み可能

PCI-Express:
 PCI-ExpressではPCIのINT線の様な専用の割り込み信号線は無く、通常のI/Oバス経由で割り込み通知が行われます。とは言え下位互換の為にPCIのINT線にソフト的な互換性を持たせたINTx emulationで処理されます。INTx emulationとAPIC及びACPIの組み合わせにより個々のデバイス毎に独立してIRQが割り当て可能に成りましたが、これだけでは依然として部分的にIRQを共有している事が有る様です。
 本格的にデバイスとIRQが一対一の対応に成るのはPCI Rev2.2で導入されたMSI及びPCI Rev3.0からのMSI-Xからの様で、PCI-ExpressもMSI/MSI-Xを継承していて、WindowsVista/2008以降のOSでMSI/MSI-Xが利用出来ます。但し全てのPCI-ExpressカードがMSI/MSI-Xに対応している訳ではないのはPCIと同様な様です。

省電力機能と割込み
 負荷を分散するという考え方とは対極的に、負荷を幾つかのコアに集中させて省電力機能により稼動していないコアを個別に休止させるという考え方が有ります。負荷を分散すれば発熱も分散出来るので局所的に疲労して寿命が縮まったりする事も無いけれど、負荷が平均的に掛かるのでコアを個別に休止させるのは難しそうです。こういったポリシーの場合は、どのコアに割り込みを掛けるかは、専らパフォーマンスに注視していれば良さそうですけれども、省電力にも配慮して幾つかのコアを休止させている場合には、休止しているコアへ割り込みを掛けるのはナンセンスだと思います。わざわざ寝ている人を起こして仕事をさせる様なもので寝ぼけている間のレイテンシが発生するし、寝かせた意味が無いと思います。その為、比較的負荷の低い状態かつ眠っていないコアへ割り込みを掛けるのが良さそうですけれども、そういったインテリジェントな設定方法を筆者は知らないのです。そもそも自作PCで省電力機能を完璧に実現するのはなかなか難しい上に、省電力状態からの復帰に失敗した時の残念な感じを味わいたくない筆者は、メーカー製のモバイルPCでしか省電力機能を使っていません。機会が有れば省電力と割り込みに付いて調査・検証してみたいとも思いますが・・・

双発電脳 と USB3.0 UASP プロトコルオーバーヘッド

NUMAノードの違いで、なんじゃこりゃぁ?というくらいの差が出てしまいました。ある程度想定していたとは言え、筆者の予想を遥かに上回っておりましてこんなに違うなら今までのUSB3.0検証は速度や負荷に付いて全てやり直しですorz

 この件に関しては Interrupt-Affinity Policy ツール が活躍しそうですが、このツールはNUMA対応が本格的に成る前のVista世代のツールなのでうまく動くかこれから検証してみます。->エラーが出ますがデバイスとコアの紐付け設定は(完全では有りませんが)機能します(後述)。
 というかWindows7/8世代では自動的に最適なスケジューリングがされる様に成っているだろうという先入観が有りましたが、個別にデバイス毎にNUMAノードを手動で設定する必要が有るとは思いもよりませんでした・・・


 下の二つのスクリーンショットを速度とCPU負荷の両面からみますと別物か?と思うくらいの差が出ている事に気付くと思いますが、二つの条件の違いはNUMAノード0で実行したか1で実行したかの違いしかありません。判り易く言えば実行するコアの位置を変えて2度実行しただけです。2番コアと8番コアで4K-QD32では最大34%もの速度差が出ています。この30%以上もの差は何度計測し直しても埋める事の出来ないものでした。検証環境の詳細は記事の最後に記載しております。

 デバイスドライバ・ワーカスレッドと別ノードでCrystalDiskMarkを実行した場合
Renesas_D720200_4KQD32_0FILL_HOSTNODE0_CDMNODE1_C.png

 デバイスドライバ・ワーカスレッドと同一ノードでCrystalDiskMarkを実行した場合
Renesas_D720200_4KQD32_0FILL_HOSTNODE0_CDMNODE0_コントローラをノード0にのみ接続_C
問題は、デバイスと同一か否かではなく、デバイスドライバのワーカスレッドらしきスレッドとアプリのスレッドが同一ノードか否かが重要だという事です。何を言ってるのか判らないかも(ryしれませんが、下の表を参照下さい。

 デフォルトのままでは、ドライバ・ワーカスレッドらしきスレッドはデバイスの位置とは無関係にランダムなノードで実行されてしまうので最速の結果を出そうとすると追いかけっこに成りがちです。
NUMA_DEVICE_AFN.png

 そこで、追いかけっこを防止するために、初めにドライバ ワーカースレッドのNUMA nodeを固定します。冒頭のInterrupt-Affinity Policyツールを使ってデバイスが接続されたNUMA nodeの特定コアにデバイスの割り込みを手動で明示的に紐付けします。これによりドライバのワーカスレッドがデバイスと同じNUMA nodeで実行される様に固定出来ます。自動設定(IrqPolicyAllCloseProcessors や IrqPolicyOneCloseProcessorなど)は筆者の環境では機能しませんでしたが手動でコア固定(IrqPolicySpecifiedProcessors)で設定すると機能しました。
USB30_NUMA_node_affinity.png
これらの設定を行う事で、最適な状態で計測出来そうです。(実際、今までより平均的にみて高速かつ低負荷に成りました。)
このツールは操作中にエラー(Registry value for affinity mask has unexpected type)が時々発生しますが無視して継続しました。このエラーはOS起動時に作成されるレジストリ上のログの型がVista世代とWin7以降で異なる事に起因する様で、実害は無い様です。(MSサポート談
このエラーが出る場合の対処方法は、下記のバッチを作り InterruptAffinityPolicyツールを利用する直前に1回だけ実行します。OSをリブートしますとログが上書きされる為、リブート後は再度バッチを実行して下さい。


@ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
SET VNAME=TargetSet

FOR /F "tokens=1,2,3,*" %%a in ('reg.exe query HKLM\SYSTEM\CurrentControlSet\Enum /s /v %VNAME%') DO (
IF /I "%%a" EQU "%VNAME%" (
IF /I "%%b" NEQ "REG_BINARY" reg.exe delete "!_key!" /v %%a /f
) ELSE (
SET _key=%%a %%b %%c %%d
)
)


下のグラフは上記の設定を行った上で更にCrystalDiskMark本体スレッドを同一のNUMA nodeに固定し、3回:100MB:0Fill設定で5回実行(つまり合計3x5=15回測定)した平均値を元にグラフ化しています。
CDM_InterruptAffinityPolicy_1台_2
全体的にみて速度が安定して底上げされた感じですが傾向としては以前の結果と同じです。傾向が以前の検証と同一でしたので同時実行などの時間の掛かるものは再検証する予定でしたが中止する事にしました。

以下は、速度とCPU負荷以外に付いて比較した表です。
USB30card.png
余談ですが、USBの規格に則って段階的な電流調整をちゃんとしている製品は、これだけ(7つ)並べて Made in Japan の BUFFALO IFC-PCIE2U3 しか無いのは少し悲しい現実ですね。

NUMAでの割り込みやデバイス接続位置については別の記事も参照下さい

以下、以前の記述


 USB3.0 はプロトコルオーバーヘッドと通信速度の相乗効果で結果的にCPU負荷が高くなってしまうのが現状の様です。

例えば、このスクリーンショットはHIGHPOINT RocketU 1142Aの4個あるUSB3.0ポートにSSDを4台接続してCrystalDiskMarkで4台同時に4K-QD32の負荷を掛けた時のCPU負荷です。概ね右側の4コアがドライバ・ワーカスレッドらしき負荷、左側の4コアがCrystalDiskMark本体のCPU負荷です(タスクマネージャにてコアとCDMプロセス間の関係設定をしており、ドライバ・ワーカスレッド負荷らしきものはスケジューラによって自動的に分散されています)。但しシーケンシャルアクセスではCPU負荷がほぼゼロです。
HIGHPOINT_4台同時

 プロトコル間の変換処理をUSB3.0の速度にあわせてCPUが行う為、高速な変換処理が求められ、結果として高速転送=高いCPU負荷となって現れるのだと思います。この現象はSATA3世代のSSDの様にランダムアクセスが高速なデバイスで顕著に成ると思われます。つまり高速なランダムアクセス=それだけプロトコル変換を多量に処理する必要が有る。という事に成るかと思います。逆にシーケンシャルアクセスの様にデータサイズに対してプロトコルヘッダが少ないケースではCPU負荷がゼロに等しい状況ですから単純なデータ転送中には転送量に対して相対的にプロトコルヘッダの量が少ない=プロトコルオーバーヘッドが殆ど発生していないと思われます。

 但し、これはCrystalDiskMarkもしくはファイルシステム自体の限界なのかもしれません。
 例えば、これは19号機のシステムドライブでCrystalDiskMarkを実行した時の4K-QD32のCPU負荷ですが8番目のコアが100%に張り付いています。この負荷はCrystalDiskMark本体ですから、CrystalDiskMark本体プログラム自身(とシステムコール=ファイルシステムやドライバ・ワーカスレッド)がボトルネックに成っています。
CDM_CPU_NO19.png

 CPU負荷を低減する目的で高性能なNICを選択する事が有りますが、NICの現状は一般には1Gbitかつ使い切っていませんから、USB3.0の5Gbitと比較して5倍以上も低速です。その1GbitのNICですらCPU負荷を気にしてプロトコルオーバーヘッドの低減策がとられているくらいですから、USB3.0の5Gbitの帯域がいかにCPUにとって負荷に成るかは容易に想像出来ると思います。

 筆者は今まで USB3.0 の検証(1,2,3,4,5)を進めてきた中でCPU負荷を見てきましたが傾向としてUSBポート数ではなくホストコントローラ1個に付き1つのシングルスレッドで動作するドライバ・ワーカスレッドが対応しているのがWindowsでは一般的な様です。例外的にTexasInstruments社のTUSB7340用ドライバはCPU負荷が非常に低かったので何らかのハード支援の仕組みが有るのではないかと思っています(後ほどデータシートを見てみます)(但しTUSB7340でもWindows8の標準ドライバではドライバ・ワーカスレッドのCPU負荷が高かったので仮にハード支援が有るとしてもMS製ドライバは汎用的に作られておりTIのハードを活かしきれていない可能性が有りそうです)。

 ホストコントローラが複数有る場合は、コントローラの数だけドライバ・ワーカスレッドが立ち上がり負荷が分散され、言い換えるとホストコントローラが1個の場合は、シングルスレッドのドライバ・ワーカスレッドが全てのUSB3.0転送のプロトコル変換を(USB3.0の高速転送にあわせて)高速に処理する事に成ります。
 この事はシングルスレッドのドライバ・ワーカスレッドによるプロトコル変換処理がボトルネックに成り得る事を意味していますので、CPUクロックやCPUアーキテクチャが関係してきそうです。後ほどCPUアーキテクチャの違いによるUSB3.0プロトコル変換処理の負荷状況を比較してみます。

 加えて、今回の記事の主題ではブログタイトルにも成っている双発電脳=デュアルソケットでの負荷を見てゆきます。永らくUSB3.0の検証を重ねてきて、ここでようやく筆者らしい変態ぶりを発揮出来そうですが、主にNUMAでホストコントローラの接続位置とCPU負荷がどの様に関係してくるか(もしくは全く関係していないか?)を検証してみようと思います。はっきり言ってNUMAでUSB3.0は誰の得にも成らない検証作業ですが、延々と真剣に取り組んでみます。

 検証を進めつつ記事を追記してゆきます。

検証環境1:17号機
DSC02089.jpg
まず、この2つの異なるノードに直結されたスロットを使い、USB3.0では基準的な位置付けのNEC(現:Renesas)製μPD720200を採用したBUFFALO IFC-PCIE2U3を接続して測定し、その結果を基準点として、検証作業を進めようと思います。
DSC02093.jpg
このカードは近年では珍しいMade in Japanです。
DSC02090-3.jpg
このカードは部品点数が多く贅沢な作りで(部品点数が多い事だけが必ずしも良い訳では有りませんが)精密かつ丁寧な作りで好感が持てます。例えば過電流保護に使われている電子部品は他社製品では抵抗値が高い旧式のポリマーPTCサーミスタが使われている事が多く、接続したデバイス側での電圧降下の主要原因に成っていますが、BUFFALOのIFC-PCIE2U3では高価な積層PTCサーミスタが利用され抵抗値が低減されデバイス側で起きる電圧降下を緩和しています。こういった細かな配慮をしている事をBUFFALOは宣伝していませんが、それがMade in Japanでもあるように思います。(但し、同じBUFFALOでも玄人志向ブランドの製品には旧式のポリマーPTCサーミスタを使った製品を多く見掛けます。)
DSC02090.jpg

今回の検証で利用したUSB3.0カード
DSC02098.jpg
※SilverStoneのSST-EC04はVbusに過電流保護回路とバックアップコンデンサを追加・交換しました。
※玄人志向USB3.0F-P7-PCIeはVbusのバックアップコンデンサを大容量品に交換しました。

補助電源はSATA電源に統一されつつあるとは言え、各製品バラバラですから、この様に延長ケーブルも適宜自作しております。(作り過ぎて赤と黒のコードが無くなってしまいましたorz)
DSC02101.jpg

NUMA とは何か?

NUMA(Non-Uniform Memory Access、ヌマ/ヌーマ、直訳すると不均一メモリアクセス)に付いてです。一般的な事は左記リンク先のWikiを参照下さい。

メモコン ( メモリーコントローラ ) がCPUに内蔵・統合されていると、CPUを複数搭載した場合に物理メモリがCPU下に点在する為、アクセス方法が不均衡かつ複雑になります。

デュアルソケット(例外的にSocket G34ではシングルソケット)の場合
NUMA-Z.png
※CPUチップと書きましたのはCPUダイの意です。チップの方がより多くの人に理解されやすいかも?と思いチップと書きました


Socket G34 のデュアルソケット
NUMA-ZG34-2SKT2.png
斜め線は通常の16BitHyperTransportの半分の8Bitリンクです。
上側にデバイスが付く可能性もあります。


ブログ趣旨とは異なりますが・・・
Socket G34の4ソケットマザーの例
NUMA-ZG34-4.png
斜め線は通常の16BitHyperTransportの半分の8Bitリンクです。
斜め線がいびつなのは、全てのCPUに対して2パス以内な事を表現したらこうなってしまいました。色分けしてもよかったのですがカラフルに成り過ぎるかなと思い・・・


 冒頭のデュアルソケットの図で言うと、例えばCPU1で処理中のスレッドがCPU2に接続されたメモリをアクセスしようとした場合、インターコネクトを挟む分だけアクセスレイテンシが発生します(実際にはキャッシュなどが複雑に絡んでいますが)。
 加えて、双方のCPUが多コアに成りますと、交差するアクセスが必然的に増え、インターコネクトの帯域を圧迫し、ボトルネックにも成り得ます。
 メモリのみならずグラフィックボードやRAIDやNIC等のI/Oデバイスへのアクセスも同様にインターコネクト経由に成りますので、益々インターコネクトの帯域を圧迫しやすい状況に成ります。
 ソケット数が増えると3番目の図の様に問題は更に複雑に成ってゆき、キャッシュコヒーレンシを維持するだけで帯域が飽和しかねません。

 そこでOSのスケジューラや、高度にチューニングされたアプリケーションでは出来るだけ近い位置に有るメモリやデバイスを扱う様にスレッドとCPUコアの対応を決めてゆく事に成ります。

 この判断に利用されるのが先日の記事で登場したACPI 2.0aのSRAT:Static Resource Affinity TableやACPI 3.0のSLIT:System Locality Distance Information TableやACPI 4.0のMSCT:Maximum System Characteristics Tableに成ります。但しWindowsの場合はSLITを無視して独自に実測した値を使ってアクセスコストを算出しているとマイクロソフトのサポートより伺っています。

 つまり、冒頭で図示しました様な配置図をOSに伝えて適切に処理する為の情報がSRAT(ACPI 2.0a以降)やSLIT(ACPI 3.0以降)やMSCT(ACPI 4.0以降)に入っているのが正常なBIOSです。そしてSRAT(ACPI 2.0a)はAPICテーブルともリンクしていましてデバイス情報とリンクしています。


Node Interleaving:
NUMAの応用技術としてNode Interleavingが有ります。

NUMA-NodeInterleaving.png

Node InterleavingはNUMAの各Nodeに接続されたメモリに対してRAID-0の様に同時・並行・交互にアクセスしてメモリアクセスを高速化する技術ですが、両刃の刃的な逆効果もありFSB同様のボトルネックや衝突が発生し易く成り、かえって遅くなるケースも有ります。

具体的には、NUMA向けに最適化されていないプログラムを高速に実行する事が出来ますが、NUMA向けに最適化されたプログラムや、古いシングルスレッドのプログラムを多数同時に実行する様な場合は逆効果となる事が多いと思われます。
従いまして、どちらが良い悪いではなく、目的と用途に合わせて設定を変更する為の予備知識として知っておいた方が良いと思います。詳しくは前回の記事に書いています

Windows 7 で NUMA が認識されない件に付いてMicrosoftのサポートに問い合わせてみる

結論:
 NUMAをOS(WindowsやLinuxなど)に認識させる事が必ずしも最良とは言えない事が判りました。
 それは後述しますNode interleavingの効果に一長一短が有る為です。

設定:
BIOS/UEFI設定で下記を行う事でNUMAとしてWindows7/2008R2に認識されると思います。(逆の設定でNUMAを認識させない事も出来ます)
 1:ACPI SRAT Table を ENABLE
 2:Node InterleavingDISABLE
 3:Memory remappingIOMMU を確認する(設定がNUMAに影響する事がある為)
 4:上記で駄目なら BIOS/UEFI を最新にする。
 5:これらの1~4で駄目な場合はRW utilityでACPI SRATを確認します(後述)
 6:それでも駄目ならマザーボードメーカ or パソコンメーカに連絡して下さい
 ※:連絡する前に後述のWindowsでNUMAの前提条件を確認して下さい

BIOS/UEFIによって多少名前が異なったり画面が異なる場合が有りますので注意下さい。
例えば Node Interleaving は Memory Node Interleaving や Node Memory Interleaving と書いてある場合が有ります。
ACPI SRAT Table は ACPI関連の設定画面にある場合と、CPU又はメモリの設定画面にある場合があり単にSRATとしか書いてない場合も有りますしまったく別の名前の場合も有ります。例えば17号機ではNUMAのON/OFFが有り、OFF = SRAT Table の DISABLE と等価な設定に成る様です。

但し、無難な設定は Node Interleaving を ENABLE にしておいた方がNUMAを意識せずとも無難な性能が出ます。
逆に、極限性能を求める場合は Node Interleaving を DISABLE にして、NUMAを意識したプログラミングや設定をする必要が有りそうです。仮想環境の構築にはNUMAを認識させて、仮想マシン単位でNUMAの割り当てをする必要が有りそうです。CGIの様にシングルスレッドのプロセスを多数起動する場合はNUMAの方が高速(OSが自動的にNUMAに適した設定で動作する為)です。古いタイプのNUMAを無視したマルチスレッドアプリは Node Interleaving を ENABLE にして NUMA ではなく SMP 化しておいた方が高速な事が多い様です。

WindowsではNUMAに付いてOS側の設定を変更する事は一切出来ません。
但し、タスクマネージャ等でNUMA-nodeごとの負荷状況を確認したり、各プロセスとNUMA-nodeの関連付けを変更したり、或いはInterrupt-Affinity Policy ツールで個々のデバイスからの割り込みを受け取るNUMA-nodeを個別に設定する事は出来ます。
加えて、アプリケーションはNUMAを意識したプログラミングを行う事が出来ます。

ACPI SRAT :
 ACPI SRAT(Static Resource Affinity Table)は、PCがNUMAである事をOSに認識させる為に最も重要な役割を担っています。
 ACPI SRATは個々のCPUコアと物理メモリアドレスが、どのNUMA NODE(Proximity domain)に所属しているかを表しています。OSはこのデータを読み取ってタスクスケジュールとメモリ割り当ての最適化を行います。
 BIOS/UEFIにバグが有ったり、BIOS/UEFI設定でDisableに成っていたり、或いは後述のNode interleavingが有効ですと、OSはCPUコアと物理メモリがどのNUMA NODEに所属するかが判りませんので、結果としてNUMAではなくSMPとして動作します。
 ACPI SRAT の中身を確認したい場合はRW utilityを使うと簡単に判ると思います。(但しSRATが存在しないシステムではSRAT自体表示されません)

 RW utilityで17号機のSRATテーブルを表示:
 RW_SRAT.png

 OSはACPI SRATに記述されたProximity domainを見てNUMA NODEを判断します。もっと言えばProximity domain = NUMA NODEと言えます。ですから、これが間違っているとNUMAを正しく認識する事が出来ません。具体的にはSRAT自体が存在しない場合や、Proximity domainが1種類のみ(例えば全てのProcessorのProximity domainが全て0の場合など)はNUMAでなくSMPとして判断されます。

 下図は15号機でRW utilityを使ってSRATから得た情報を元にしたCPUと物理メモリアドレスの関連付けです。
 SRAT_S2915_v401d_Bata-3.png

 RAMMapを使うと、物理アドレス上のマッピングが判りますので、上記のSRATと組み合わせて見れば楽しそうです。MSにはRAMMapを次期バージョンでNUMA対応にしてくださいとお願いしておきました。ソースが有れば自分でNUMA対応版を作れるのですが・・・


Node Interleaving :
 NUMAが登場する以前から Memory interleaving は存在しましたが Node interleaving はその拡張版です。
 Memory interleaving がメモリアクセス高速化の目的で複数バンクを同時・並行・交互アクセスしたり、或いは複数チャネルを同時・並行・交互アクセスして高速化させるのと同様に Node interleaving は複数の NUMA NODE にまたがってメモリを同時・並行・交互アクセスする手法で、必然的にSMP的なイメージに近づきます。
 NUMA-NodeInterleaving.png
 この手法のメリットは、複数の NUMA NODE に接続されたメモリに対して同時・並行・交互にアクセスする事でメモリのバス幅を倍増させてパフォーマンスを向上する事ですが、デメリットとして従来のシステムでFSBがボトルネックに成っていたのと同様の事が起きて逆に遅くなってしまうケースが有ります。
※このブログはタイトルに書いてあります通り“デュアルソケット”を対象にしておりますので4ソケット以上の場合にNode interleavingがどの様に働くのかは未調査ですが、御存知の方がいましたらコメントなど頂けますと幸いです。

Node interleaving と NUMA の効果@15号機
 NUMA_SMP_INTERLEVING2.png
 この様にアプリによって結果が判れます。CPUキャッシュ内で収まるケースでは、ここまで顕著な差は出ませんが、この二つのベンチマークは両者とも円周率の演算ですから多倍長精度演算をしており、比較的大きなメモリ空間を端から端までなめる様に演算しているはずで、従ってメモリ負荷が高まり、NUMAやNodeInterleavingの効果を測定するのに適したベンチと言えそうです。
 HyperPIは、昔の80386時代に製作されたシングルスレッドのベンチマークをベースに、それを多数同時実行していますが、このケースではOSのスケジューラが適切にCPUコアとメモリを個々のプロセスに割り当てた事でインターコネクトのボトルネック(或いはインターコネクトを挟む事による遅延)が回避された結果NUMAが最も良い結果に成ったと思われます。
 逆にy-cruncherはNUMAを想定していないマルチスレッドアプリ(もしくはNUMAに適さないアルゴリズム)の為にNUMAでは最悪の結果になり、逆にNode interleavingによる負荷分散効果が非常に良い方向に出たのだと思われます。具体的には2億5千万桁の演算に必要な連続したメモリ空間を多数のスレッドが共有しつつ同時アクセスしていると思われ、NUMAでy-cruncherの場合はOSのスケジューラがメモリ配置を分散せずに片側ノードに集中してしまったためにメモリ負荷が片方のノードに集中してしまい、そこにボトルネックが発生した可能性が有ります。

NUMAでのチューニング:
 この記事でUSB3.0のUASP(USB Attached SCSI Protocol)で発生するプロトコルオーバーヘッドの負荷をNUMAで最適化する手法を例にチューニング手法を検証しています。

WindowsでNUMAの前提条件:
 ・Windows 7 64Bit/8 64Bit/Server 2008R2/Server 2012
 ・下記のいづれかのCPUソケットかつCPUを実装している事
 ・Socket 940 2CPUソケット以上
 ・Socket F(LGA 1027) 2CPUソケット以上

 ・Socket C32(LGA 1207) 2CPUソケット
 ・Socket G34(1974/1944) 1CPUソケット以上

 ・Socket B(LGA 1366) 2CPUソケット
 ・Socket LS(LGA 1567) 2CPUソケット以上
 ・Socket B2(LGA 1356) 2CPUソケット
 ・Socket R(LGA 2011) 2CPUソケット以上



以下、マイクロソフトに問い合わせた時の状況です。上記のマトメをする以前に書きましたので間違い等が多いかもしれません。


昨日書きました「Windows 7 で NUMA が認識されない件」に付いて、Microsoftの有償サポートを利用して問い合わせてみる事にしました。

自分で調べて解決しようとしたのですが、ネット上でそういった情報には辿り着けませんでした。もちろん英語でも検索してみましたがSQLサーバ関連の情報、NIC関連の情報、それにSP1適用前の情報にしか辿り着けませんでした。(この時に気付けば良かったのですが、SQLサーバのチューニングにNode Interleavingの設定を行っている方が結構居る様でした。SQLサーバは大量のデータを扱う為にメモリ関連のチューニングが非常に重要な位置を占めますから、もう少し詳しく注意深く見ていればマイクロソフトに問い合わせなくとも良かったかもしれませんorz)

NUMAを意識してプログラムを作る様な人達はLinux利用者が多数を占め、その為にWindowsでのNUMA関連の情報が少ないのではないかと思います。更にWindowsでのNUMAサポートが今回の様にいまひとつな状況な事もLinuxへ流れてゆく原因の一つかもしれません。Linuxであれば自分で原因究明して設定を任意に変更する事も可能ですがWindowsですとカーネルソースは非公開ですし設定変更する様なツールも無いので何も手出し出来ません。

といいますか、恐らくWindows7のバグじゃあないかと思っている訳ですが、そうでないのかもしれず、いづれにしろ解決手段を得るまで有償/無償に関わらず調査を進めてみようと思います。そもそもOpteronのマルチCPU構成ではNUMA以外に有り得ない訳ですが・・・

Nehalem以降のIntel CPUも含め、今やワークステーションではNUMAが当然ですし、NUMAを意識したプログラミングが出来ないと最大パフォーマンスを引き出す事が出来ません。

前置きが長くなりましたが、さっそくMicrosoftのサポートへ連絡です。
筆者は個人ユーザですので、最初に個人向けの有償サポート窓口へ電話を入れてみました。
 サ窓口「今回はどういった御用件でしょうか?」
 あっ、アニメ声の女の子に窓口対応させてるのかMSやるな
 「Windows7 が NUMA NODE を正しく認識しないのですが」
 以降、クレジットカード番号と個人情報をガッツリ根こそぎおさえられ有料サポートが開始します。
金4,200円也。受付の女性に代わり男性技術者が電話口に・・・
 「どういった御質問でしょうか?」
 「Windows7 が NUMA NODE を正しく認識しないのですが」
 「ヌーマモードですか」
 「いえ、NUMA NODE です。エヌ、オー、ディー、イー、ノードです」
 「NUMAとは何ですか?」
 「そこからですか・・・」
 「はい、判りませんので説明して下さい」
 Windows7の目玉機能の一つとしてNUMA NODEを認識して・・・略」
 「なるほど、続けてください」
 NUMAとは複数CPUを搭載したシステムで個々のCPUがメモリを・・・略」
 「それはWindows7の機能ですか?」
 Windows7の目玉機能の一つとしてNUMA NODEを認識して・・・略」
 「もしかして何かご機嫌が悪いような?」
 「お金を払ってWindows7に付いてサポートを受けようとしているのに、私がWindows7の新機能に付いてサポートの方に詳しく説明をしている状態では、サポートを受ける事が出来るのか少々心配なのですが?」
 「なるほど、少々お待ち下さい」
 ---少し待たされるーーー
 「コンシューマ向けのサポートで受けられる範囲を超えた高度な質問のため・・・」
 タスクマネージャの表示メニューに付いてですからWindows7で使える通常の機能に付いて質問している訳ですが?
 「こういった質問ですと技術者向け窓口に成りまして金額が変わりますが?」
 「納得いきませんが仕方ありません、どちらに連絡すればよいでしょうか?」
 「こちらで電話をまわしますので、しばらくお待ち下さい。」
 ---結構待たされるーーー
 携帯のバッテリー切れるorz

充電器につないで再度電話(挨拶等略)
 サ窓口「技術者向けサポートですと33,390円になりますが宜しいでしょうか?」
 「さ、さっ、さんまんさんぜんさん・・・」
 サ窓口「三万三千三百九十円になります」
 金参萬参千参百九拾円也・・・
 金額もプロ仕様ですが、受付嬢もアニメ声のコンシューマサポートとは異なり、フォーマルな印象です。メイドと女性執事くらいの差でしょうか・・・
 「恐らくWindows7のバグじゃないかと思うのですが3万払ってバグ報告ですか・・・」
 サ窓口「はぁ・・・」
 「バグじゃなかったらスミマセンが・・・解決策を・・・」
 サ窓口「どうしますか?」
 「判りました・・・御願いします。」 あぁ~グラボが1枚買えるよォ~
 サ窓口「最終的には、どういった質問でしょうか?」
 「・・・ Windows7 が NUMA = Non Uniform Memory Access を正しく・・・略」
 サ窓口「ご購入されたパソコンに初めから入っていたWindowsでしょうか?」
 複数台ありまして、パッケージ版、DSP、MSDNライセンス等ごちゃごちゃで・・・
 サ窓口「ご質問のパソコンは、購入時に入っていたWindowsでしょうか?」
 複数台ありまして、パッケージ版、DSP、MSDNライセンス等ごちゃごちゃで・・・
 サ窓口「折り返し技術サポートから電話しますので、ご都合の良い時間を教えて下さい」
 ---時間帯を伝え、電話を切る。---

15:20サポートより電話あり(挨拶等略)
 「NUMA NODEの件ですが基本的にマザーボード側のACPIからの情報で判断しておりますので、BIOSが対応していないとNUMAとして認識できません。」
 おっ、ようやく話が通じる人が来た。
 「ACPIですか・・・NUMAかどうかはCPUで決まると思うのですが・・・」
 「OS側としましてはCPUに関係なく、あくまでもACPIからの情報でNUMAかどうかを判断しております。」
 「それ以外の可能性は?」
 「報告が上がっているものとして256CPU以上の環境でSMPとして誤認識されてしまう現象がありました」
 「それ以外には有りませんか?」
 「基本的にWindowsの認証取得したパソコンですと、そういったテストを予め行っていますが自作用のマザーボードですとちょっと」
 自作はいつもこの手で逃げられる訳だが・・・SIerに成らねば・・・
 「私の所有する5台の異なるNUMA機のうち2台ですから40%の確率で不具合が出ている訳ですが、にもかかわらず全く報告が無いのでしょうか?」
 「はい、それ以外では・・・但し、その他の可能性も無いとは言い切れません」
 「BIOSのACPIが原因か、それともOS側の原因なのかは、どうやって切り分けするのでしょうか?何か調べる手段はありますか?」
 「それを調べるにはBSODを発生させてOSのメモリダンプを取得して頂く必要が御座います。」
 「仮にBIOSのACPIが原因だったとして、OS側の設定等で回避する方法はありますか?」
 「この件に付きましては、OS側の設定で何か出来る訳でなく、あくまでもACPIの情報に従って動作する事に成ります。」
 「つまり、その場合BIOSを修正する以外に解決手段が無いと?」
 「はい、カーネルメモリ上にACPIのテーブルがそのままコピーされていますので、OSはそれを見て判断します。」
 
 と言う事で、今まで安定稼動していた15号機と19号機で強制的にブルースクリーンを発生させて、いったんOSを落さないといけなくなりましたorz

 ブルースクリーンで生成されるカーネルメモリダンプをMicrosoftに送って調査して頂く訳ですが、仮にBIOSのACPIが原因だったとして、自分でBIOSのACPIテーブルを修正するか、それともマザーボードメーカー(両方ともTYAN)に対応してもらうのか、前途多難な気もしてきました、しかも問題が起きてるのは1台でなく2台ありますから・・・

 強制ブルースクリーンは、今まで落ちた事の無いPCではしたくない行為ですが仕方ありません・・・思い切って実行しリブート後にZIP形式でまとめて送りました。後は結果待ちです。

10月9日午前、サポートより再度電話あり(挨拶等略)
 「カーネルメモリダンプを受け取りました。これから調査に入りまして本日中には一次回答が出来るかと思います。」
 「宜しく御願いします」
 「もしWindows7側の問題でしたら料金は発生しませんので御安心下さい」
 「なるほど」
 「ですがBIOS側の問題でしたら33,390円の技術料が発生しますので御了承下さい」
 つまりバグを疑って報告した場合、Windowsのバグだったら無料、Windows側のバグじゃなかったら有料、確率1/2の賭けって事か・・・
 「その場合はマザーボードメーカーに依頼してBIOSを改修して頂くのが正道というわけですね?或いは自分で治すか・・・」
 ※法的には、こういったケースでインターフェース部分に限ってはリバースエンジニアリングが許容されています。内部のコアな部分は当然リバース禁止なのですが、インターフェースまで禁止にしてしまうと何も前に進まなくなってしまう事を考慮してだと思います。
 「はい、ハードウエア側の問題をWindows側のパッチで対処するというのは最近の方針としてやらない方向になっています」
 「ところでMSCTを参照しているといった内容をメールで頂きましたが、MSCTはACPI 4.0から盛り込まれた仕様の様ですが、と言う事はNUMAではシステム要件がACPI 4.0と言う事でしょうか?」
 「MSCTに付きましてはNUMA distanceの追加情報になりましてMSCTが無くてもNUMAとして認識されます」
 ※10月10日のメールでMSCTはNUMA distanceではないという訂正文が届きました。筆者は鵜呑みにしていましたが、ちゃんと自分で規格書を読むべきだったと反省しています。
 「NUMA distanceに付いてはACPI 3.0で追加に成った様ですか?」
 「そちらはSRAT側の追加情報です」
 ※10月10日のメールでNUMA distanceはACPI 3.0で追加になったSLIT:System Locality Distance Information Tableでしたという訂正文が届きました。筆者は鵜呑みにしていましたが、ちゃんと自分で規格書を読むべきだったと反省しています。というか筆者の指摘の方が正しかった訳ですが・・・
 「SRATはACPI 2.0で追加され2.0aからSpecには御社のホームページへのリンクが書いてありましたが、これがリンク切れでした。それがACPI 3.0からはSpec上に直接詳細に記載される様に成った様ですが?」
 「ACPI 3.0ではSRATに項目が追加されました・・・略」(略としたのは、この記事に書いてある事を読んでいる様な内容でしたので・・・)
 「結局、NUMAのシステム要件としてはACPI 2.0aで問題ないのでしょうか?」
 「はい、ACPI 2.0でNUMAとして認識されます」
 「問題の発生しているマザーボードのBIOSでSRATのEnable/Disableが出来ましてNUMA関連の設定といった説明に成っていました。、それをEnableにしていますが問題が起きています」
 「SRATが有効だとしてもテーブル上でノードが単一の設定に成っていましたらNUMAノードが認識できませんので、そういった可能性もあります」
 「なるほど、いづれにしろカーネルメモリダンプを見てからですね」
 「はい」

と言う事でNUMAのシステム要件はACPI 2.0aという事が明確に成りましたので、一歩前進です。

10月9日午後、サポートより再度電話あり(挨拶等略)
 「カーネルメモリダンプを調査した結果、BIOSのACPIテーブルに問題が見つかりました。詳細はメール致しましたが、ご覧に成りましたか?」
 「すみません、未だ見ていませんが、マザーボードメーカーに不具合を指摘出来る様な資料が頂けますと助かります。」
 「SRAT部分のメモリダンプを添付しましたが、英語でコメントを入れた方が良いかもしれませんね。」
 「はい、よろしければお願いします」
 「具体的にはK10_D(15号機:Tyan S2915A2NRF-E:BIOS v401)のマシンはSRATが存在しません」
 「BIOS画面ではSRATのENABLE/DISABLE設定が可能でENABLEに成っていますが、それでもSRATが無いのですか?」
 「はい、実際にはそうなっていました」
 「なるほど」
 「Bulldozer機(19号機:Tyan S8225AGM4NRF:BIOS v302)はSRATが存在するのですがNUMA NODEが1つしか定義されていません」
 「そうでしたか・・・」

と言う事で、マザーボードメーカ(Tyan)に不具合申請する為の資料(問題箇所をピンポイントで指摘出来る具体的なデータ付きで)を作って頂く事に成りました。データは明日頂けるようです。


以下、問い合わせ後の調査



15号機:Tyan S2915A2NRF-E:BIOS v401に付いて


 Tyan S2915A2NRF-E には BIOS v401 の後にベータ版の BIOS v401d が公開されています。
 更新履歴では SRAT に付いて全く触れられていない事と、ベータ版なのであえて試していなかったのですが、BIOS v401 には SRAT が存在しない事が判りましたので駄目元でベータ版 BIOS 401d を入れてみましたら、あっけなくNUMAとして認識されましたorz
SRATを直したなら更新履歴に明記してくれよと言いたいです。それにベータ版BIOSを使うのは少々抵抗が有りますが、これしかNUMA対応出来ないのですから仕方ないですね。未だ試してはいませんがv401でもNode InterleavingをDISABLEにする事でNUMA認識されるかもしれません。
Opteron 2439 SE2



19号機:Tyan S8225:BIOS v302に付いて


 読者様にコメントで教えて頂きまして Memory Node Interleaving (19号機では Node Interleaving)を Auto から DISABLE に変更しましたら NUMA として認識されましたorz
 MSに対してバグとか言ってしまい申し訳なかったと思う反面、MSの3万円サポートからは Node Interleaving に関する情報は一切出てきませんでしたので、なんだろな・・・という気もします。とはいえ Node Interleaving はハード側の事ですから MS が知らなくても(又は、知っていて伝えなくとも)それはそれで仕方の無い事です。
19GNUMA.png



NUMA distanceに付いて


この問題に付いて調べ始めた頃から若干気に成っていたのですが、Windows7がNUMAを認識出来たとしてもNUMA distanceは必ずしも正しく認識していないのではないか?と言う気がしていました。
それに付いて10月9日の回答でACPI 4.0のMSCTを採用していないとNUMA Distanceが認識できないと言っていましたのでその通りなのだと思います。
※10月10日のメールでNUMA DistanceはSLIT(ACPI 3.0で追加された)で設定されていますがWindowsはSLITを無視しているという回答でした。では、どうやってアクセスコストを割り出しているのか?というとWindowsが独自に実測して割り出しているらしく、その値は非公開なのだそうです・・・

以下はNUMAとして認識されているPCでCoreinfo -n -mを実行した時のレポートです。

17号機:
 Logical Processor to NUMA Node Map:
 ****---- NUMA Node 0
 ----**** NUMA Node 1
 Calculating Cross-NUMA Node Access Cost...
 Approximate Cross-NUMA Node Access Cost (relative to fastest):
    00 01
 00: 1.0 1.2
 01: 1.2 1.2

13号機:
 Logical Processor to NUMA Node Map:
 ******------ NUMA Node 0
 ------****** NUMA Node 1
 Calculating Cross-NUMA Node Access Cost...
 Approximate Cross-NUMA Node Access Cost (relative to fastest):
    00 01
 00: 1.0 1.3
 01: 1.4 1.1
 2回目実行時
 Approximate Cross-NUMA Node Access Cost (relative to fastest):
    00 01
 00: 1.1 1.3
 01: 1.2 1.0

11号機:
 Logical Processor to NUMA Node Map:
 **-- NUMA Node 0
 --** NUMA Node 1
 Calculating Cross-NUMA Node Access Cost...
 Approximate Cross-NUMA Node Access Cost (relative to fastest):
    00 01
 00: 1.4 1.5
 01: 1.6 1.0

実行するつど結果が変わりますのでCoreinfoでは実測しているのだと思いますが、念のため後ほど聞いてみようと思います。→聞いてみましたところ、実測値の為、つど変わるという回答でした。


以下、ACPIでのNUMA対応に付いて


なるほど確かにLinuxでも同様にACPIを見てNUMA判定している様です。

ACPI 規格 (Advanced Configuration and Power Interface Specification) にNUMAに関する記述が有りました。

ACPI Revision 2.0
 ACPI Rev 2.0 の時代には NUMA という表現ではなく、processor-memory proximity として記載されていました。そして初期のACPI 2.0ではNUMA関連の仕様にエラッタ(具体的な記述が無い)が有りRev2.0aで修正されていました。つまりNUMA機のシステム要件には最も古い規格に互換性を持たせた場合でもACPI 2.0aと書くべきと思います。その修正内容は http://www.microsoft.com/HWDEV/design/SRAT.htm を参照する形でリンクが追記されたのですが、このページはリンク切れです。リンクの切れたドキュメントは読者の方に教えて頂きこちらで参照可能です。

ACPI Revision 3.0
 ACPI Rev 3.0 では上記のリンクではなく規格書上に明記される形に変更に成りました、その為にリンクが廃止されました(MSサポートからの回答で確認・・・出来ればACPI 2.0a時点の仕様も見たい訳ですが、それが叶いません)。更にACPI 3.0では新しくNUMA Distancingに付いてSLITが追加されています。但しWindows7/Server2008R2は、この情報を無視してアクセスコストを独自に算出し、その値を参照するAPIは無く外部には非公開だそうです。

ACPI Revision 4.0
 Microsoft有償サポートからメールで送られてきた情報によりますと、MSCT(Maximum System Characteristics Table)も関係していると書いてありました。但し関係していると書いてあるのみで必須かどうかは書いてありませんでした。その後の電話対応で必須ではないという回答を頂きました。
 ACPI規格によりますとMSCTはACPI Rev4.0で初登場します。
 実際11号機(SuperMicro H8DCi : K8 Opteron)はNUMAとしてWindows7に正しく認識されておりますがBIOS最終更新が2008年10月、対してACPI 4.0の仕様公開が2009年6月です。ACPI 4.0の発表はWindows7の発売と同時期です。

Microsoftの関連ページ
 NUMAハードウエアデザインに付いて
 NUMAのサポートに付いて
 Windows7 システム要件
 Windows Server2008 R2 システム要件
 64ビットWindowsについて(ACPI 2.0に付いての記述)


以下、NUMAに付いて


NUMA(Non-Uniform Memory Access、ヌマ/ヌーマ)
ところでNUMA=AMD Opteronという誤解が有りそうなので、ここで整理しておこうと思いますがPCではメモコンを内蔵したCPUで複数ソケットの場合にNUMAに成ります。例外としてSocket G34はシングルCPUで既にNUMAです。従いまして64BitのWindows7であればエディションに関係なくNUMA対応していると思います。また広義にはGPGPUもNUMAと言えるかもしれません。

2012年10月現在、下記がNUMAです。
・Socket 940 2CPU以上
・Socket F 2CPU以上

・Socket C32 2CPU
・Socket G34 1CPU以上

・Socket 1366 2CPU
・Socket 1567 2CPU以上
・Socket 1356 2CPU
・Socket 2011 2CPU以上


全てのOpteronとNehalem以降のXEONで2CPU以上ですとNUMAです。例外的にはMagny-CoursとInterlagosが1CPUでNUMAとなります。


以下、NUMAとACPIの時系列に付いて


1999年:
 Micron Technology MTSAM64GZ (SAMURAI64M2 ノースブリッジ2基搭載)
2000年:
 5月:IBM NUMA-Q 2000 (PentiumIII XEON NUMA 最大64CPU)発売
 8月:ACPI Spec Rev2.0発表(SRAT:Static Resource Affinity Table にてNUMAを規定)
2002年:
 ACPI Spec Rev2.0a発表(SRATエラッタを修正しNUMA実装を可能に)
2003年:
 AMD Opteron(Socket 940)発売、x86-64 PC初のNUMA 最大8ノード対応
2004年:
 ACPI Spec Rev3.0発表(NUMA Distancing = SLIT の追加)
2005年:
 AMD Dual-Core Opteron 発売、単1のNUMAノード内に複数コアを持つ複雑な構成に
2006年:
 AMD Opteron(Socket F)発売、仮想化にハード対応
2007年:
 AMD Opteron(K10)発売、NUMAとして2世代目のアーキテクチャ
2008年:
 Intel Nehalem-EP(Socket 1366)発売、Intel製x86-64初のNUMA製品
2009年:
 ACPI Spec Rev4.0発表(MSCT:Maximum System Characteristics Table)
 Windows7/Server2008R2発売 NUMA用API及びタスクマネージャをNUMAに対応。
2010年:
 AMD Magny-Cours(Socket G34)発売、1ソケットで初のNUMA
 Intel Nehalem-EX(Socket 1567)発売、Intel初の複数ノードのNUMAに対応


以下、問題発生機のBIOSの状況


今まではHyperTransport関連のBIOS項目しか見ていなかったのですが、ACPIだとすると・・・BIOS設定でACPI関連の所にNUMAの設定が有るかも?

これから見てみます。↓

15号機(Tyan S2915A2NRF-E)はPhoenix BIOSです。
SRAT(System Resource Affinity Table)の設定がENABLE/DISABLE出来る様に成っていましたがテーブルの中身までは判りません・・・しかし画面右側のHELPにはNUMA用の設定ですよと明記されています。ccNUMAと書いてあるのは Cache Coherent NUMA の略で、つまりCPU内部のL1やL2といったキャッシュをCPU間で整合性を保ったままNUMAを構築するという意味です。
他にMSCT(Maximum System Characteristics Table)も関係している様ですがMSCT関連の設定項目は見当たりません。
DSC01882.jpg

19号機(Tyan S8225)はAMI BIOSです。
ACPIを1.0~3.0で指定出来ますが、その他にNUMA関係の設定項目がありません。
項目が無いからと言ってテーブルまで無いかと言うとそんな事はないと思いますが・・・
元々3.0で使ってましたが、試しに2.0でリブートしてみましたが状況変わらずでした。
DSC01884.jpg

とにかく、NUMAの状態が正確に設定出来ていないとPC全体のパフォーマンスに影響しますし、逆に修正すればアプリの動作が本来の速度にまで高められるというか遅くなっていたのが元に戻る訳です。

けど、これ、いってみれば3万円自腹でBIOSとOSの結合テストしてデバッグしてるだけですよね?

原因はTyanマザーのBIOS-ACPIテーブル構成にバグが有るか、MicrosoftのOS側にバグが有るかの、バグの2択しか有り得ない訳ですが、それを調べるのに筆者は3万支払う訳です・・・
なんでしょね・・・

念の為、BIOSを最新にUPDATEしてみようと思いましたが、既に最新でした・・・
しいて言えば15号機(S2915A2NRF-E)の最新BIOSはBetaなので一つ前の正式版を使ってますがBetaで対応したのはUSB関連とRadeon HD5xxxの相性問題のみでIstanbul対応は15号機に既に搭載されているv401で対応済みです。→にもかかわらずBeta版のv401dで15号機はNUMA対応出来ましたorz

残るは19号機のみです・・・
19号機は読者様の御指摘を頂きましてNode Interleavingの設定変更でNUMAとして認識されましたorz
プロフィール

DualSocketTheWorld

Author:DualSocketTheWorld
自作を始めて20台目くらいになりますが、最初からデュアルソケット限定(始めた当時はデュアルスロット)で自作しており、近年になってAMD K6を試したくなりSocket7でK6-2+のシングル構成で組んだのがシングル初です。

シングルマザー(含:シングルソケットマルチコア)や4ソケット以上の自作は基本的にしませんし、メーカー製PCの改造も基本的にはしません(ノートPCのSSD化くらいはしますが・・・)

基本路線はワークステーションと呼ばれる分野での自作で、OSもWindows系であればProfesionalが主な対象に成ります。

ゲーマーの様なOverClockは行わず、WS路線としてハイエンドCPUとハイエンドGPUの組み合わせで定格或いはDownClockで発熱を抑えつつ、その時のアーキテクチャに置いて爆速かつ静音を目指し、30年以上の長期に渡り稼動状態をキープする事を目指します。

※基本的にリンクフリーです。どこでも自由にどうぞ。

※画像は時々変ります。

※お決まりの文章ですが、改造は個人の責任で行ってください。ここに記載された情報は間違いを含んでいる可能性が有り、それを元に製作や改造などをして失敗しても筆者は一切責任持てませんので悪しからず。

筆者略歴:
小学生時代にゴミ捨て場で拾ったジャンクテレビ数台を分解して部品を取り出し真空管アンプを自作、中学生時代にPC8801mkⅡsrでZ80アセンブラを始める。社会人になって初のプログラムは弾道計算、後に医療系・金融系プログラマ~SEを経て100~200人規模プロジェクトのジェネラルマネジャを数年経験、独立して起業。現在は不動産所得で半引退生活。
(人物特定を避ける目的で一部経歴を変更しています)

最新記事
最新コメント
最新トラックバック
月別アーカイブ
カテゴリ
アクセスカウンター
検索フォーム
RSSリンクの表示
リンク
ブロとも申請フォーム

この人とブロともになる

QRコード
QR