本発明は、処理、装置、システム、物質の組成、コンピュータ読み取り可能な格納媒体上に具現化されたコンピュータプログラム製品、および/または、プロセッサ(プロセッサに接続されたメモリに格納および/またはそのメモリによって提供される命令を実行するよう構成されたプロセッサ)を含め、様々な形態で実装されうる。本明細書では、これらの実装または本発明が取りうる任意の他の形態を、技術と呼ぶ。一般に、開示された処理の工程の順序は、本発明の範囲内で変更されてもよい。特に言及しない限り、タスクを実行するよう構成されるものとして記載されたプロセッサまたはメモリなどの構成要素は、ある時間にタスクを実行するよう一時的に構成された一般的な構成要素として、または、タスクを実行するよう製造された特定の構成要素として実装されてよい。本明細書では、「プロセッサ」という用語は、1または複数のデバイス、回路、および/または、コンピュータプログラム命令などのデータを処理するよう構成された処理コアを指すものとする。
以下では、本発明の原理を示す図面を参照しつつ、本発明の1または複数の実施形態の詳細な説明を行う。本発明は、かかる実施形態に関連して説明されているが、どの実施形態にも限定されない。本発明の範囲は、特許請求の範囲によってのみ限定されるものであり、本発明は、多くの代替物、変形物、および、等価物を含む。以下の説明では、本発明の完全な理解を提供するために、多くの具体的な詳細事項が記載されている。これらの詳細事項は、例示を目的としたものであり、本発明は、これらの具体的な詳細事項の一部または全てがなくとも特許請求の範囲に従って実施可能である。簡単のために、本発明に関連する技術分野で周知の技術要素については、本発明が必要以上にわかりにくくならないように、詳細には説明していない。
図1は、コンピュータシステムの一実施形態を示す。システム100は、本明細書では「企業向けスーパーコンピュータ」および「メインフレーム」とも呼ばれる。図の例において、システム100は、近接して位置する(例えば、同じラック内に位置する)複数のノード(例えば、ノード102〜108)を含む。別の実施形態において、(例えば、同じ施設内に位置する)複数のラックのノードが、システムで用いられてもよい。さらに、本明細書に記載の技術は、分散型システムと併せて利用されてもよい。
ノードは、10ギガビットEthernet、ダイレクトPCI−to−PCI、および/または、InfiniBandなど、高速相互接続(110)と相互接続されている。各ノードは、コモディティサーバクラスのハードウェア構成要素(例えば、取り付けられた周辺機器または包含された周辺機器を備えるラック内のブレード)を備える。図1に示す例において、各ノードは、複数の物理プロセッサチップを備える。各物理プロセッサチップ(「ソケット」とも呼ぶ)は、複数のコアを備えており、各コアは、複数のハイパースレッドを有する。
図2に示すように、システム100の物理構造は、(下から)ハイパースレッド(230)、コア(210〜224)、物理プロセッサチップ(202〜208)、および、ノード(102〜108(図から省略され省略記号で表されたノード104、106などを含む))の階層を形成する。図2に示すツリーは、ハードウェア構成によって規定された固定サイズである。
後に詳述するように、各企業向けスーパーコンピュータ(例えば、システム100)は、単一のオペレーティングシステムを実行する。オペレーティングシステムおよび任意のアプリケーションの両方が、標準的な市販のソフトウェアであってよく、システム100上で動作しうる。本明細書に記載の例において、オペレーティングシステムはLinux(登録商標、以下同じ)であるが、Microsoft Windows、Mac OS X、または、FreeBSDなど、その他のオペレーティングシステムが用いられてもよい。
従来の仮想コンピュータ環境では、複数の仮想マシンが、単一の物理マシン上で動作しうる。このシナリオは、図3Aに図示されている。具体的には、3つの仮想マシン(302〜306)が、単一の物理マシン(308)上で3つのゲストオペレーティングシステムを実行しており、物理マシンは、独自のホストオペレーティングシステムを有する。対照的に、本明細書に記載の技術を用いると、複数の物理マシン(354〜358)が、図3Bに示すように、単一の仮想オペレーティングシステム(352)を集合的に実行する。
ソフトウェアスタックの一例が、図4Aに示されている。かかるスタックは、通例、従来のコンピュータ環境で用いられてよい。図4Aに示すスタック内では、アプリケーション(402)が、データベースエンジン(404)上にあり、次いで、データベースエンジン(404)は、オペレーティングシステム(406)上にあり、その下に、ハードウェア(408)がある。図4Bは、いくつかの実施形態において用いられるソフトウェアスタックを示している。図4Aに示したスタックと同様に、アプリケーション(452)が、データベースエンジン(454)上にあり、次いで、データベースエンジン(454)は、オペレーティングシステム(456)上にある。しかしながら、オペレーティングシステムの下かつハードウェアの上には、システムの動作をリアルタイムで観察し、システムの動作時にシステムの要求に一致するようにシステムリソースを最適化するソフトウェアの層(本明細書ではハイパーカーネルと呼ぶ)がある。ハイパーカーネルは、概念的には、一群のコモディティサーバのRAM、プロセッサ、および、I/O(例えば、ストレージ、ネットワーキングリソースのための入力出力リソース)を統合し、その統合したセットをオペレーティングシステムに提示する。この抽象化のため、オペレーティングシステムからは、プロセッサ、メモリ、および、I/Oの集合的なセットを含む単一の大型コンピュータが見える。後に詳述するように、ハイパーカーネルは、リソースの利用を最適化する。ハイパーカーネルは、ネットワークおよびストレージなど、他のI/Oシステムリソースの最適化も助けうる。いくつかの実施形態において、実行中のソフトウェアの観察およびプロファイルに基づいて、パフォーマンス指標(ヒント)が、システムパフォーマンス全体をさらに改善しうるシステムの動的パフォーマンスについて、上層(例えば、データベース管理システム)に提供される。
ハイパーカーネルは、すべての主要なマイクロプロセッサ、メモリ、相互接続、永続記憶装置、および、ネットワーキングアーキテクチャに移植されうる。さらに、ハードウェア技術が(例えば、新たなプロセッサ、新たなメモリ技術、新たな相互接続などで)進化するにつれ、ハイパーカーネルは、産業の進化を活用する必要に応じて修正されうる。
図4Bに示すように、オペレーティングシステム456は、一連のノード(458〜462)にわたって集合的に動作しており、各ノードは、サーバハードウェア上で動作するハイパーカーネルを有する。具体的には、オペレーティングシステムは、一群のハイパーカーネルによって定義された仮想環境上で動作している。後に詳述するように、オペレーティングシステム456の視点では、オペレーティングシステムは、個々のノード458〜462のハードウェアリソースすべてを含む単一のハードウェアプラットフォーム上で動作している。したがって、各ノードが1TBのRAMを備える場合、オペレーティングシステムからは、自身が、3TBのRAMを備えたハードウェアプラットフォーム上で動作しているように見える。その他のリソース(処理能力およびI/Oリソースなど)も、同様に、オペレーティングシステムの視点で集合的に利用可能になりうる。
図5は、一例のシステム上のハードウェアに対するオペレーティングシステムの視点の一例を示す図である。具体的には、オペレーティングシステム(502)は、プロセッサ504〜508および物理共有メモリ510の上で動作する。既述のように、オペレーティングシステムは、従来のコンピュータシステム上または図1に示すような企業向けスーパーコンピュータ上のいずれかで動作できる。いずれにしても、オペレーティングシステムから見ると、自身は、プロセッサ504〜508および物理共有メモリ510にアクセスできることになる。
図6Aは、単一のノード上のハードウェアに対するハイパースレッドの視点の一例を示す図である。この例において、ノードは、H1(602)〜H4(608)で示された4つのハイパースレッドを有する。各ハイパースレッドは、物理共有メモリ612のすべての部分にアクセスできる。物理共有メモリ612は、線形メモリであり、位置0から最大量「max」までラベル付けされている。ノードは、3つのレベルのキャッシュ(610)も備える。
図6Bは、一例のシステム上のハードウェアに対するハイパーカーネルの視点の一例を示す図である。この例では、3つのノード(652〜656)が、企業向けスーパーコンピュータに含まれる。3つのノードの各々が、4つのハイパースレッド、物理共有メモリ、および、キャッシュを有する(すなわち、各ノードは、図6Aに示したノード600の一実施形態である)。所与のノード(例えば、ノード652)上のハイパースレッドは、図6Aに示す視点と同じ視点を有する。しかしながら、ハイパーカーネルは、すべてのノード上のすべてのリソースを認識している(すなわち、ハイパーカーネルには、12のハイパースレッドおよびすべての物理共有メモリが見える)。図6Bに示した例において、所与のハイパースレッド(例えば、ハイパースレッド658、「H1−4」)は、ノード番号(例えば、「1」)の後にハイパースレッド番号(例えば、「4」)を続けてラベル付けされる。
図7は、一例の企業向けスーパーコンピュータシステム上のハードウェアに対するオペレーティングシステムの視点の一例を示す図である。オペレーティングシステムには、P1〜Pmax(702)として図7に示された複数の「仮想化プロセッサ」が見える。仮想化プロセッサは、企業スーパーコンピュータに含まれるすべてのノードにわたるハイパースレッドの総数に対応する。したがって、図6Bの例を用いると、合計12のハイパースレッドが3つのノードにわたって存在する場合、企業向けスーパーコンピュータ上で動作するオペレーティングシステムにとっては、合計12の仮想化プロセッサが見えることになる。オペレーティングシステムには、すべてのノードにわたる物理メモリの総量に等しいサイズの大型の物理的な線形メモリのように見える「仮想物理メモリ」(704)も見える。
後に詳述するように、ハイパーカーネルは、実行中のシステムの観察に基づいて、キャッシュメモリの利用および仮想プロセッサの配置を動的に最適化する。「仮想プロセッサ」は、そのゲストオペレーティングシステムに知られている計算エンジン(すなわち、何らかのオペレーティングシステムコンテキストまたは状態を有するもの)である。後に詳述するように、「シャドープロセッサ」は、匿名の仮想プロセッサ(すなわち、仮想プロセッサであったが、現在は、そのオペレーティングシステムコンテキストを放棄しており、ハイパーカーネルにのみ知られるコンテキストを有するもの)である。
リソースの仮想化
メモリの仮想化
上述のように、物理構成において、各ノードは、メモリ内での位置を表す一連のメモリアドレスを有する。このように、(例えば、図6Bに示したように)3つのノードを有する物理構成においては、各々がアドレス0x123456を有する3つのメモリ位置がある。対照的に、仮想構成においては、すべてのメモリアドレスが一意的であり、それらの3つのノードに含まれるすべてのメモリの総計を表す。仮想構成では、すべてのメモリが共有され、すべてのメモリキャッシュがコヒーレントである。いくつかの実施形態において、メモリは、単調増加するメモリアドレスで、一連の連続的なブロックにさらに分割される。本明細書に記載される例において、各ページは、4Kバイトのメモリを有するが、適用できる場合、その他の分割が用いられてもよい。「ブロック」という用語は、本明細書では、メモリ位置の連続的な配列を記述するのに用いられる。いくつかの実施形態において、「ブロック」は「ページ」である。
プロセッサの仮想化
オペレーティングシステムから見られる仮想プロセッサ(例えば、図7の仮想プロセッサ706)は、物理構成内のハイパースレッド上に実装されるが、位置独立でありうる。したがって、オペレーティングシステムは、単一の物理サーバ上で動作する500のプロセッサを有すると考えるが、実際には、各々100プロセッサの5ノードを有しうる。(つまり、図6Bに示したように、オペレーティングシステムは、単一の物理サーバ上で動作する12のプロセッサを有すると考える)。仮想プロセッサ上で実行される計算は、計算が実行されている場合にハイパースレッド上の物理構成によって、または、仮想プロセッサが動作中ではない場合(すなわち、計算の中断またはストールの状態)に「継続(continuation)」で記述される。
本明細書で用いられているように、「継続」は、仮想プロセッサの状態を表す。各継続は:
・プロセッサ状態(すなわち、退避レジスタなど)を有する 。
・実行に向けてリーフノードに継続をインテリジェントに割り当てる方法に関する情報でスケジューラオブジェクトを導く1セットのパフォーマンスインジケータを有する。
・オペレーティングシステムの考えるプロセッサがこの継続の割り当てられる物理プロセッサであることを示す仮想プロセッサ識別子を有する。
・この継続が待っている(おそらくは、エンプティである)イベントを有する。
・以下を含む状態を有する。「イベント待機」または「レディ」。
I/Oの仮想化
I/Oシステムは、プロセッサおよびメモリと同様のパラダイムに従う。デバイスは、物理構成における物理アドレスおよび仮想構成における仮想アドレスを有する。(後に詳述する)計算を移動させる時に、例えば、I/O動作に関連するメモリバッファがある場合、利用されるI/Oデバイスは、それらが関連するメモリと同じ場所に配置されれば、より性能が高くなる可能性があり、状況に応じて移動可能である。
リソースマップ
リソースマップは、仮想構成と物理構成との間の翻訳に用いられる。以下は、様々な実施形態において企業向けスーパーコンピュータによって用いられる3つのタイプのリソースマップである。
「物理リソースマップ」は、各ノードで利用可能な物理リソースを記述するテーブルである。それは、例えば、各ノード上のプロセッサ、デバイスの数およびタイプ、利用可能なメモリおよびその物理アドレスの範囲、などを含む。いくつかの実施形態において、このテーブルは、読み出し専用であり、起動時に固定される。
「初期仮想リソースマップ」が、オペレーティングシステムの起動の前に固定され、オペレーティングシステムの観点から利用可能な仮想リソースを記述する。構成は、オペレーティングシステムによって読み取り可能である。一部の例において、下層のハードウェアリソースと、一対一で一致しない(オペレーティングシステムの視点からの)システムを構成することが望ましい場合がある。一例として、オペレーティングシステムにとっては、より多くのメモリおよびより少ないコアを有することが望ましい場合がある。これは、メモリ対コアの比を変更することによって(すなわち、初期仮想リソースマップを修正することによって)達成できる。
「現行のリソースマップ」が、各ハイパーカーネルインスタンスによって作成および維持される。このマップは、各ノードの視点からの仮想リソースマップと物理リソースマップとの間の現行のマッピングを記述する。仮想リソースマップ内の各エントリに対して、仮想リソースへ現在割り当てられている物理リソースの定義が維持される。最初(例えば、起動時に)、現行のリソースマップは、初期仮想リソースマップのコピーである。ハイパーカーネルは、リソース負荷の特性を観察しながら、時間と共に現行のリソースマップを修正し、仮想リソースに対する物理リソースのマッピングを動的に変更する(および逆も行う)。例えば、仮想化マシンにおけるイーサネットコントローラeth27の位置の定義は、異なるハードウェアコントローラを、異なる時間に参照しうる。現行のリソースマップは、必要に応じて、仮想ハードウェアリソースマッピングを動的に修正するためにハイパーカーネル(仮想メモリサブシステムなど)によって用いられる。
リソースマイグレーション(移動)の概要
本明細書に記載の技術を用いれば、仮想リソースを物理位置の間で移動できる。上述のように、オペレーティングシステムは、仮想システムに関する情報を提供されるが、その情報は、物理システムと一致する必要はない。
以下の例において、企業のスーパーコンピュータが、単一のノードに収まりうるよりも大きい大型のインメモリデータベースを保持すると仮定する。データベースの一部は、第1ノード「ノード1」にある。異なるノード「ノード2」上のコアの1つが、ノード1によって所有されノード2上のキャッシュにローカルに存在しないデータにアクセスを試みていると仮定する。ノード2上のコアは、アクセスできると思われる(ただし、アクセスできない)データへのアクセスを試みているので、メモリアクセス違反を受信する。後に詳述するように、例外は、ハイパーカーネルにおいて処理される。
その状況を解決できる一方法は、必要なメモリ領域をノード2に移した後に、制御をオペレーティングシステムに戻す(オペレーティングシステムは、次に、制御をデータベースシステムに戻す)ことによる方法である。次いで、ソフトウェアは、意図されたように進むことができる(すなわち、アクセス違反が起こらなかったかのように)。
多くの場合、上記のノード2が必要とするメモリの同じ領域ブロックにアクセスを試みている他のノード(例えば、「ノード3」)内の1または複数の他のコアが存在しうる。ノード3は、同じデータにアクセスを試みている場合もあるし、移されたメモリに含まれる別のデータにアクセスしている場合もある(「偽共有」とも呼ぶ)。データは、ノード3に移動されることができるが、ノード2上のコアが、二回目にデータを要求した場合、データは、ノード2に戻される必要があり(すなわち、潜在的にデータの往復を繰り返す)、これは、遅くて無駄が多い場合がある。コア間のデータの往復移動を避けるための一方法は、両方のコアと、データに関連するブロックが、同じ場所にあることを認識することである。本明細書に記載の技術を用いれば、メモリおよび計算が、同じノードに存在するように移行されうる。そうすることにより、データへのより高速なアクセスの可能性が高くなり、ローカルキャッシュに格納されたデータを共有する可能性が高くなる。
アクセス違反が起きると、イベントが(システム依存の方法で)トリガされ、それにハイパーカーネルが応答する。かかるイベントに対処する方法の一例は、パニックルーチンの呼び出しによる方法である。適切であれば、その他のアプローチが用いられてもよい。後に詳述するように、ハイパーカーネルは、イベントの原因を分析し、イベントに対処するために適切な戦略(例えば、低レベルトランザクション)を決定する。上述のように、イベントに対処する一方法は、ハイパーカーネル仮想化メモリの1または複数のブロックが、或るノードのメモリから別のノードのメモリへ転送される方法である。次いで、転送が開始され、対応するリソースマップが更新される。継続は、再開された時に行う次のことが、転送の完了後にオペレーティングシステムに制御を戻すことになるように、イベントテーブル(後述する)と呼ばれる共有メモリ内のローカルテーブルに配置される準備が整うように構築される。要求されているメモリを含むノードに仮想プロセッサを移動させる決定、または、或るノードから別のノードへ仮想メモリ(およびその仮想メモリアドレス)を移動させる決定もなされうる。様々な実施形態において、ハイパーカーネルは、イベントに対処する時に、どの(仮想)リソースが移動すべきか、いつ移動させるべきか、および、(物理位置に関して)どこへ移動すべきか、の3つの決定を行う。
タイダルツリー(TIDALTREE)
図2に示した物理階層構造は、1セットの「スケジューラオブジェクト」(すなわち、データ構造)を含む類似のソフトウェア階層を有し、各スケジューラオブジェクトは、後述の1セットの特徴を有する。スケジューラオブジェクトは、「タイダルツリー」を形成し、これは、ツリーの各ノードがスケジューラオブジェクトであるインメモリツリーデータ構造である。各スケジューラオブジェクトは、スーパーコンピュータの物理構造の要素に対応する(ただし、必ずしも逆は成り立たない)ので、マシン全体に対して1つのノード(例えば、図2に示すノード100)、システムの各物理ノードに対して1つのノード(図2に示すノード102)、マシン全体を含む物理ノード上の各マルチコアソケットに対して1つのノード(例えば、図2に示したノード202)、各ソケットの各コアに対して1つのノード(例えば、図2に示すノード210)、そのコア上の各ハイパースレッドに対して1つのノード(例えば、図2に示すノード232)が存在する。
各スケジューラオブジェクトsは、
・物理的構成要素(例えば、ラック、ブレード、ソケット、コア、ハイパースレッド)に関連する。
・ツリーのルートを除いて、(後に詳述するように)その動作を方向付けることに部分的に関与する親スケジューラオブジェクトを有する。
・各々がスケジューラオブジェクトである1セットの子オブジェクトを有する。これは、リーフ(例えば、ハイパースレッド)ノードについては空のセットである。後に詳述するように、作業を管理して、その子オブジェクトに、そして、間接的に孫オブジェクトなどに、作業を割り当てる(または、割り当て直す)のが、スケジューラオブジェクトsの役割である(すなわち、sは、sをルートとするサブツリー内のすべてのノードを管理する)。
・(上述のように)1セットの継続である作業キューを有する。
・作業を管理して割り当てる(または割り当て直す)ことに同じく関与する(おそらくはエンプティの)セットのI/Oデバイスを有する。
各ノードは、何らかのキャッシュメモリの形態の層と潜在的に関連付けられうる。キャッシュ階層は、スケジューラオブジェクトが高くなるほど、通常は、計算が階層の対応するレベルのキャッシュを効率的に利用することが遅くなるという意味では、ツリーの階層に従う。物理ノードに対応するスケジューラオブジェクトのキャッシュは、そのノードに対応するメモリのキャッシュでありうる。物理ノード上のメモリは、仮想マシンのメモリのキャッシュと考えることができる。
リソースマイグレーション−追加情報
ハイパーカーネルは、仮想構成が存在する仮想ハードウェアの一部をシミュレートする。それは、イベント駆動型アーキテクチャであり、翻訳された物理ハードウェアイベントだけでなく、他のノード上で動作するハイパーカーネルコードによって生成されたノード間ハイパーカーネルメッセージの受信など、ソフトイベントも処理する。
上述のように、ハイパーカーネルにとって重要な割り込みイベントが発生すると、ハイパーカーネルは、割り込みに応答する方法を決定する。制御がオペレーティングシステムに戻される前に、任意のより高い優先順位の割り込みが認識され、適切な動作が取られる。また、上述のように、ハイパーカーネルは、(1)特定のイベント後にどのリソースが移動すべきか、(2)いつそれらを移動させるか、および、(3)それらのリソースはどこに移動すべきか、といった3つの別個の決定を行い得る。
以下の例において、仮想マシン内のスケジューラオブジェクト「s」が、定常状態であると仮定する。物理ノードに対応する各スケジューラオブジェクトは、それに割り当てられた1セットの物理プロセッサソケットを有する。これらのソケット内のハイパースレッドは、ビジーであってもそうでなくてもよい。物理ノードは、さらに、いくらかの固定量のメインメモリと、いくつかのネットワークデバイスなど、1セットのI/Oデバイスと、を有する。スケジューラオブジェクトsは、ノードに対応する場合、ネットワークと、sをルートとするサブツリー内のノードに割り当てられた他のI/Oデバイスとの管理にも関与する。以下では、リソースが同期または非同期的イベントのいずれかの後にどのように移動しうるのかを説明する。
同期イベントによってトリガされるマイグレーション
以下の例では、リーフノードスケジューラオブジェクトsと、sに割り当てられた仮想プロセッサpが存在すると仮定する。リーフノードスケジューラオブジェクトsは、アプリケーションの代わりに、アプリケーションまたはオペレーティングシステムコードを実行しているとする。リーフノードが無限ループに入っていないと仮定すると、pは、最終的に、何らかの理由(例えば、I/O動作、ページフォールトなどの完了の待機)で、実行すべき作業がなくなる(すなわち、ストールする)。pが実際にストールすることを許容する代わりに、ハイパーカーネルは、ストールされた計算に関する情報を或る他のノードに移して、他のノードのプロセッサの1つに、ストールした継続の「責任」を持たせるのか、または、ストールした計算に対するノードの「責任」を維持し、その代わりに現行のノードに関連リソースを移すのかを決定する。
したがって、ストールは、以下の2つの方法のいずれかで処理される:計算が、現在リソースを有する物理ノードに移されるか、あるいは、リソースが、リソースを要求した物理ノードに移される。ストールの処理のための擬似コードの例は、後の「ルーチンの例」セクションで(「OnStall」ルーチンとして)提供される。
ストールを処理する方法などの決定は、イベントの到着順、仮想マシン上で実行中の計算の状態、キャッシュの状態、システムまたはノードへの負荷、ならびに、多くのその他のことなど、多くのことに依存しうる。決定は、動的になされる、すなわち、時間の所与の時点に利用可能な最良の情報に基づいてなされる。
ストールした計算の記録
ストールした計算は、「継続」と呼ばれるデータ構造に記録される。継続は、例えば、「イベント待機」または「レディ」でありうる状態を有する。ストールした計算は、状態「イベント待機」を持つ新たに作成された継続として記録される。(例えば、イベントの検出により)ストールの理由が満たされると、対応する継続の状態は、「レディ」に変更される。「レディ」状態を持つ各継続は、最終的に実行に向けてスケジューリングされるように、スケジューラオブジェクトの「待機キュー」に格納される。対照的に、「イベント待機」状態を持つ任意の継続は、どのスケジューラオブジェクトの待機キューにも格納されない。その代わり、見つからないリソースの受信など、対応する計算をストールさせたハードウェアイベントの発生が予測される物理ノードのローカル共有メモリに格納される。
さらに、新たに作成された継続は、その作成の原因となったストールイベントに関連付けられる。(ストール)イベントと、これらのイベントを待つ継続との間のこのマッピングは、非同期イベントの迅速なディスパッチを可能にする(後述の「handleEvent」を参照)。継続とイベントとの間のマッピングは、「イベントテーブル」と呼ばれるテーブルに格納され、対応する物理ノードの共有メモリ内に保持される。各物理ノードは、独自のイベントテーブルを有し、物理ノードのイベントテーブルは、物理ノード上のすべてのコアによって直接的にアドレス可能である。物理ノードのイベントテーブルに記録されたすべての予定されたイベントは、物理ノード上で発生しうるハードウェアイベントに対応する。物理ノードnにマッピングされたスケジューラオブジェクトsは、nを表し、nのイベントテーブルは、sと関連付けられる。一部の例において、いくつかの継続が、同じイベントを待っている場合があり、イベントがトリガされた時に、何らかの曖昧性の除去が求められうる。
継続は、「InitContinuation」ルーチンを用いて構築される。計算を移動させる決定がなされた場合、リソースを保持するリモート物理ノードが、ストールされた計算に対応する継続を構築し、リモート物理ノードのイベントテーブルにそれを格納する。その継続が再開すると、リソースは利用可能になる。実際には、ハイパーカーネルは、異なるノードに仮想プロセッサを移している。
リソースを移動させる決定がなされた場合、ストールを経験したノードは、リソースの移送を要求し、InitContinuationを用いて継続を構築し、ローカルイベントテーブルにそれを格納する。リソースの受信後、継続は、タイダルツリー内の適切なノードにアタッチされ、その継続が再開されると、リソースは、一般に、利用可能かつ可視になる。実際には、仮想リソースは、それを要求したノードに移送されている。
イベントテーブル内に継続を配置することにより、イベントを受信するプロセッサが、ローカルイベントテーブル内で関連する継続を迅速に見つけることが保証されることに注意されたい。計算のストールの理由は、満たされることになる。
ストールに対処すると、仮想プロセッサpは、実際には一時停止される。ストールを処理して、再開すべき新たな継続を見つけるまでの合間に、pは、「匿名のシャドープロセッサ」になる、すなわち、オペレーティングシステムに知られているIDのないプロセッサになる。次いで、このシャドープロセッサは、再開すべき新たな継続を探す。これの一例が、後に詳述する「assignProcessor」ルーチンに見られる。
表記
仮想プロセッサpをストールしたイベントをeとする。eは、ある物理ノードnのローカルハードウェアによってトリガされると仮定する。特に、rが、ストールイベントの発生の原因となったリソースであると仮定する。リソースrは、メモリのブロック、I/O動作、または、ネットワーク動作でありうる。pは、スケジューラオブジェクトsに割り当てられると仮定し、スケジューラオブジェクトsは、物理ノードnを表すスケジューラオブジェクトをルートとするサブツリーに属する。
On−Stall
on−stallルーチンの一例に対する擬似コードを、以下の「ルーチンの例」セクションで提供する。migration−continuation関数は、リソースが移動すべきではない、すなわち、計算が移動すべきであると、ノードn内のプロセッサpが決定した場合かつその場合に限り、trueを返す。これは、ノード間でのrの移動の履歴および頻度、rのタイプ、移動のコスト、rを待つnのローカルイベントテーブル内のイベントの数、システム負荷など、多くの要因によって決定されうる。例えば、リソースを待つnのローカルイベントテーブルに格納された継続がある場合、そのリソースを移動することが望ましくない場合がある。
マイグレーションの恩恵を受ける様々なパターンのイベントが存在する。アクセス違反のようなこれらのパターンのイベントを記述する1つのアプローチは、形式言語理論である。正規(すなわち、チョムスキーのタイプ3)言語は、有限状態オートマトンによって認識することができる。さらに、コンパクトで柔軟な表記を用いて、観察されるイベントの記述は、正規言語の文(またはチョムスキー配列(Chomsky sequence))としてなされることができ、認識は、対応する有限状態オートマトンにおける状態遷移としてモデル化されうる。イベントの完全なチョムスキー配列が見られる場合、migration−continuationは、それに応じて評価される:有限状態オートマトンがチョムスキー配列を受け入れる場合、条件は満たされ、そうでない場合には満たされない。最小化された有限状態マシンの長さは、保持する必要のある履歴の量を規定する。
様々な実施形態において、すべてのイベントがローカルに起こり、イベントを受信する物理ノード上のハイパーカーネルが、それを処理しなければならない−真の同期イベントは、物理ノード間で発生しないと仮定される。ノード間でのマイグレーション戦略を調整するために、「メッセージ」が用いられる。プロセッサまたはシャドープロセッサが、一般に、メッセージの受信を待たない点で、メッセージ「送信」は、ノードの視点からは同期的であるが、メッセージ「受信」は、非同期的である。メッセージが到着すると、仮想割り込みとしてハイパーカーネルによって処理される。一実施形態において、ハイパーカーネルは、処理を待つメッセージがある間は、プロセッサが継続を再開することを許容しない。したがって、制御がオペレーティングシステムに戻される前に、キューがチェックされ、オペレーティングシステムに制御を戻す前に、あらゆるメッセージが処理される。
スケジューラオブジェクトsおよび継続cについて、ツリーの検索を導くために、コスト関数cost(s,c)を利用できる。pの複数の先祖がエンプティではないキューを有する場合に、pは、エンプティではない待機キューで見つかった第1先祖でその検索の停止を望まない場合がある。最適化戦略で用いられるメトリックに応じて、pの選択は、pとその選択された先祖との間の距離にだけでなく、その他のパラメータ(待機キューの長さなど)にも依存してよい。
スケジューラオブジェクトの(空でない)待機キューにおける「最良適合」継続を返すために、関数find−best−within(s)を利用できる。考慮できるパラメータの例は以下を含む。
1.キューにおける位置
2.pと、継続に記録された最後の位置との間の関係性(それらの位置が近いほど、キャッシュエントリの再利用にとって良くなる)
3.キューに内の継続に記録されたパフォーマンスインジケータ
cost関数およびfind−best−within関数は、所与のシステム内で適用可能なようにカスタマイズできる。
非同期イベントによってトリガされるマイグレーション
非同期イベントの例は以下を含む。パケットの受信、I/O転送の完了、リソースの受信、リソースを要求するメッセージの受信、など。一般に、オペレーティングシステムによって管理されるハードウェアデバイスに対応するイベントを受信するハイパーカーネルは、そのイベントに関連する継続をスケジューラオブジェクトsに供給する必要がある。そうすることにより、sは、適切なスケジューラオブジェクトに、そして最終的には、その継続によって表されたオペレーティングシステムによって管理される計算に、この継続を利用可能にする。他方で、イベントが、別の物理ノード上のハイパーカーネルからのメッセージの受信である場合、ハイパーカーネルは、それを直接処理できる。
説明を簡単にするために、本明細書に記載の例においては、イベントに関連する継続が1つだけであると仮定する。本明細書に記載の手順は、必要に応じて、複数の継続が同じイベントに関連する例に一般化できる。
いくつかの実施形態において、継続を配置すべきスケジューラオブジェクトの検索は、その継続を構築したツリーのリーフで始まり、その後、(計算がこのノードで以前に実行された場合には)上方に進む。そうすることにより、キャッシュエントリの再利用の可能性が高くなる。
Handle−Event
handle−eventルーチンの一例に対する擬似コードを、以下の「ルーチンの例」セクションで提供する。コスト関数cost(s,c)は、スケジューリングオブジェクトsにcを割り当てる適合性を決定するのに役立つ関数である。コスト関数は、待機キューのサイズ、(キャッシュエントリが再利用される可能性を高めるための)sとcの元々のスケジューリングノードとの間のノードトラバース距離、ならびに、仮想プロセッサ、物理プロセッサ、および、継続の履歴など、様々なパラメータに依存しうる。sに近いスケジューラオブジェクトの待機キューの含む継続がすでに多すぎる場合、すべての新たに追加された継続が実行に向けてスケジューリングされるまでに比較的長い時間が掛かりうる。cost(s,c)に寄与する条件の例を以下に記載しており、それらの状態は、適用可能なようにカスタマイズできる。
コスト
コスト関数は、継続を選択してオブジェクトをスケジューリングする時にオプションを評価するために用いられる。コスト関数は、重み付き因子の総和として表現できる:
cost=w1f1 x 1+w2f2 x 2+...+wnfn x n
ここで、wiは、対応する因子の重要度を示し、xiは、指数を示す。
因子fiの例を、以下のコストの各々について記載する。重みwiおよび指数xiは、様々な方法で決定できる(経験的に決定する、シミュレーションによって決定する、など)。初期の重みおよび指数は、様々な応用のニーズに合わせることが可能であり、パフォーマンスを改善するために、管理者によって調整されうる。重みは、システムがアクティブである間に調整可能であり、重みの変更は、ハイパーカーネルのセマンティクスを変更せず、動作パフォーマンス特徴だけを変更する。
考慮できる因子の例は以下を含む。
・最後のプロセッサがこのスケジューラオブジェクトを評価してからの時間の長さ
・タイダルツリー内でのスケジューラオブジェクトの高さ
・作業キューの長さ
・保留状態(すなわち、或るアプリケーションが特定の理由でこのリソースを保存した場合でありうる)
・ノード仕様(すなわち、ノード自体が、非稼働状態にされた可能性がある、または、問題がある、何らかの形で特殊な機能を有する、など)
・キュー内の継続の齢
・この継続を最も実行しそうにない物理プロセッサ
・この継続を最も実行しそうにない仮想プロセッサ
・この継続を最後に実行していたノード
・キャッシュの「温度」(キャッシュは、再利用される可能性のあるエントリを有する場合に「温かい」。キャッシュは、再利用可能なキャッシュエントリを有する可能性が低い場合に「冷たい」)
・継続のグループメンバーシップ(すなわち、継続は、計算グループの一部であってよく、グループの各要素は、グループのその他のメンバに対する何らかのアフィニティを有する)
・パフォーマンスインジケータ(ヒント)および特別な要件
例
「OnStall」および「assignProcessor」
図8は、リソースを選択的に移動させるための処理の一実施形態を示す。いくつかの実施形態において、処理800は、OnStallルーチンと共に実行されるなど、ハイパーカーネルによって実行される。処理は、コア(または、プロセッサチップがハイパースレッドを支持するか否かに応じて、コアに含まれるハイパーカーネル)がブロックされている旨の示唆が受信される工程802で始まる。一例として、ハイパースレッドがアクセスできないリソース(例えば、ハイパースレッドを保持するノードとは異なるノードに配置されたRAM)の要求を、そのハイパースレッドが直接的または間接的に受信すると仮定する。ハイパースレッドがリソースにアクセスできない(すなわち、アクセス違反が発生する)場合、割り込みが起こり、それは、工程802でハイパーカーネルによって、インターセプト、キャッチ、または、その他の方法で受信される。特に、ハイパーカーネルは、(提供するよう指示されたリソースへアクセスできないので)ハイパースレッドがブロックされている旨の示唆を工程802で受信する。ブロック状態を報告することに加えて、ハイパーカーネルは、アクセスするよう指示されたメモリアドレスおよび試みられたアクセスのタイプ(例えば、読み出し、書き込み、または、修正)などの情報を提供する。
工程804において、ハイパーカーネルは、必要とされるメモリが(例えば、ブロックされたハイパースレッドが位置するノードへ)移動されるべきか、要求処理が再マッピングされる(すなわち、仮想プロセッサが別のノードに移される)べきか、を決定する。決定は、必要とされるメモリが位置する場所、キャッシュの温度、ハイパースレッドを保持するノードへの作業負荷、および、必要とされるメモリを保持するノードへの作業負荷(例えば、過負荷または低負荷)など、様々な因子に基づきうる。いくつかの実施形態において、ノードの作業負荷は、タイダルツリーにおける平均キュー長に少なくとも部分的に基づいて決定される。
ハイパーカーネルは、メモリが移動されるべきであると決定した場合、その現行のリソースマップを用いて、どのノードが必要とされるメモリを保持する可能性があるかを判定し、そのノードへメッセージを送信して、リソースを要求する。ハイパーカーネルは、さらに、継続を作成し、そのイベントテーブルにその継続を配置する。したがって、工程802においてブロックされたハイパースレッドは、他の作業を引き受けるために解放され、assignProcessorルーチンを用いて別の仮想プロセッサに割り当てられうる。
ハイパーカーネルは、優先度の高さに基づいて、そのメッセージキューをチェックする。ハイパーカーネルが、自身の接触したノード(すなわち、「第1接触ノード」)からメッセージを受信すると、いくつかの実施形態において、2つの応答の内の1つが受信される。応答は、第1接触ノードが、必要とされるリソースを有することを示唆してよい(そして、リソースを提供してよい)あるいは、メッセージは、接触ノードが(例えば、そのノードがリソースを別のノードに提供したために)リソースをもはや持たないことを示唆してもよい。後者の状況において、第1接触ノードは、それがリソースを送信する送信先のノード(すなわち、「第2ノード」)のIDを提供し、ハイパーカーネルは、リソースを要求する第2メッセージを、この例では第2ノードに送信できる。様々な実施形態において、第2ノードが、自身もリソースを持たないこと(例えば、第3ノードに提供したこと)をハイパーカーネルに報告した場合、ハイパーカーネルは、リソースを要求し続けるのではなく、第3ノードに継続を送信することを選んでよい。継続を送信するか、リソースを継続するかを決定する際に、他の閾値を用いてもよい(例えば、4回の試行)。さらに、リソースを要求するか、継続を送信するかを決定する際に、様々な基準を用いてよい(例えば、コスト関数に従う)。
ハイパーカーネルは、継続が転送されるべきである(すなわち、ローカルにリソースを受信するのではなく、計算が別のノードに送信されるべきである)と決定した場合、リモートノード(すなわち、必要とされるリソースを持つノード)に、リモートノードがそれ自身の物理アドレス空間内に継続を構築するために利用できる情報を提供する。リモートノード(すなわち、継続を受信するノード)が、自身の必要とするリソースすべてを有する(すなわち、最初のアクセス違反を引き起こしたリソースを保有する)場合、継続は、遠隔ノードのイベントテーブルに配置される必要はなく、その代わりにタイダルツリーに配置されてよい。リモートノードが、継続を処理するためにさらなるリソースを必要とする場合、受信された継続は、遠隔ノードのイベントテーブル内に配置される。
図9は、階層的な動的スケジューリングを実行するための処理の一実施形態を示す。いくつかの実施形態において、処理900は、assignProcessorルーチンと共に実行されるなど、ハイパーカーネルによって実行される。処理は、ハイパースレッドが割り当てられるべきである旨の示唆が受信される工程902で始まる。処理900は、複数の方法で呼び出されうる。一例として、処理900は、ハイパースレッドが利用可能である(すなわち、実行すべき現在の作業を持たない)時に呼び出されうる。これは、例えば、継続がなされるべきであるとハイパーカーネルが(例えば、工程804において)決定した時に、起こりうる。以前にブロックされたハイパースレッドは、ブロックの対象となった計算を処理する責任がもはやない(すなわち、ハイパースレッドが「匿名のシャドープロセッサ」になる)ので、利用可能になる。第2の例として、処理900は、以前には利用不可能であったリソースが現在は利用可能である旨のメッセージが(例えば、ハイパーカーネルによって)受信された時に呼び出されうる。ハイパーカーネルは、リソースを必要としていた計算を再開するために、ハイパースレッドをロケートする必要がある。もともとリソースの不足によってブロックされていたハイパースレッドが、リソースの受信後に計算を再開するハイパースレッドである必要はないことに注意されたい。
工程904では、タイダルツリーにおいて、実行の準備が整っている継続が検索され、ハイパースレッドが再開すべきものとして、1つの継続が選択される。様々な実施形態において、タイダルツリーは、リーフレベルから上向きに検索され、コスト関数が、ハイパースレッドにどの継続を割り当てるのかを決定するために用いられる。一例として、ハイパースレッドが利用可能になった時に、最も長い時間にわたってキューに入れられていた継続が、割り当てられうる。リーフレベルに待機中の継続がない場合、または、コスト関数によって指定された閾値外にある場合、ハイパースレッドに割り当てるべき適切な継続が、タイダルツリーで検索される(例えば、コアレベル、次に、ソケットレベル、次に、ノードレベルで)。ハイパースレッドがノードレベルで再開するのに適切な継続が見つからなかった場合、そのノードのハイパーカーネルは、ルートに接触する。ノードレベルで継続が見つからない1つの典型的な理由は、そのノードが完全に利用されるのに十分な作業がないことである。いくつかの実施形態において、ノードまたはノードの一部は、エネルギ節約状態に入りうる。
時系列
説明のために、例においては、「スワップ」動作が、継続およびメモリの移動に用いられるが、実際には、これは、すべての実施形態で必要なことでない。
図10は、初期のメモリ割り当ておよびプロセッサ割り当ての一例を示す。具体的には、図10の領域1002は、メモリの物理ブロック(左側)と、メモリの現在のオーナー(中央列)との間のハイパーカーネルのマッピングを示す。右の列は、メモリの以前のオーナーを示す。これは初期のメモリ割り当てであるため、現在および直前のオーナー列は、同じ値を保持する。図10の領域1004は、システム仮想プロセッサ(左側)と、物理ノード(中央列)/コア番号(右列)との間のハイパーカーネルのマッピングを示す。
仮想プロセッサP00が位置8FFFFを読み出すためにメモリ要求し、ハイパーカーネルがP00と同じノード(すなわち、ノード0)へ8FFFFを含む1または複数のメモリブロックを移動することを決定すると仮定する。ブロック8FFFは、ノード2に位置する。したがって、図11に示すように、8FFFFを含むブロックは、ノード0に移され、別のブロックが、(排除が必要であり、ブロックが有効である場合には)スワップアウトされる。
次に、仮想プロセッサP06が位置81FFFを読み出すためにメモリ要求をすると仮定する。このブロックのコンテンツは、ノード0に(図11に示すように)移動されている。ハイパーカーネルは、メモリを再び移動させるのではなく、計算が移動されるべきであると決定してよい。したがって、図12に示すように、仮想プロセッサP06は、ノード0に移動され、仮想プロセッサP01とスワップされてよい。
パフォーマンス情報
ロックおよびその他の同期装置
様々な実施形態において、ロックのような同期メカニズムの利用が最小限である。例えば、ロックは、スケジューラオブジェクト上でキューの挿入およびキュー継続の除去を行うため、および、イベントテーブルを維持するために用いられる。
コードパス長
いくつかの実施形態において、すべてのコードパスの(最大)長は、静的コード解析を通して決定され、その結果、ハイパーカーネル自体で費やされる評価可能な有界の時間が得られる。すべてのデータ構造が、例えば、インデックス付きの配列として、事前に割り当てられうる。タイダルツリーのノードは、起動時に決定され、それらのトラバースの際のステップ数と同様に、不変である。1つの可変長計算が、作業キューの長さと関連があるが、それすら有界でありえ、最悪ケース推定値が計算されうる。別の実施形態では、その他の可変長計算が用いられる。
スタティックストレージ
様々な実施形態において、ハイパーカーネルで必要とされるすべてのデータ構造が静的であり、起動時に決定されるので、動的メモリ割り当てまたはガベージコレクションの必要性はない。
物理メモリ
ハイパーカーネルによって用いられるすべてのメモリが物理メモリであるので、内部動作に必要なページテーブルも仮想メモリもなく(例えば、それが管理している仮想リソースの管理を除く)、さらに、ハイパーカーネルがオペレーティングシステムと共存するのを助ける。
データの共有と整合性の維持
一部の例において、例えば、オペレーティングシステムに提示される仮想マシンの概念的統合性を保つために、あるノードのデータ構造の変化が、別のノードの対応する変化と協調される。本明細書に記載のデータ構造の多くは、「ノードローカル」であり、移動する必要がないか、または、不変であり複製される。ノードローカルであるデータ構造は、ノード上のすべてのハイパースレッドに可視であり、それらによってアドレス可能である。ノードローカルではない(したがって、協調を必要とする)データ構造の例は、現在のリソースマップ(またはその一部)と、タイダルツリーのルートと、移動する継続(すなわち、或るノードから別のノードへ論理的に移動する必要がありうる継続)と、を含む。
様々な技術が、十分な程度の整合性を維持するために用いられてよい。一部の技術は同期的であり、すべての変化がすべてのノードにとって同時に可視的になること(すなわち、「即時整合性」)を仮定する。他の技術は、より緩和されたソリューションを可能にし、「結果整合性」を追求する。上述のように、企業のスーパーコンピュータの物理ノードは、1または複数の高速相互接続を介して接続されている。ハイパーカーネルの複数のインスタンスが、物理ノード間でメッセージおよびリソースをやり取りするために相互接続される。
現行のリソースマップの更新
各物理ノードnは、物理リソースマップの同じコピー、初期の仮想リソースマップ、および、現行のリソースマップから(例えば、起動時に)開始する。各ノードは、現行のリソースマップの独自のコピーを維持する。
いくつかの実施形態において、現行のリソースマップ内のリソースrの各エントリは、以下を有する。
1.ローカルロック。その結果、物理ノード上の複数のハイパースレッドが同時にrを修正できなくなる
2.現在リソースを所有するノードを特定するノード番号
3.最後にrを所有していた時から要求された回数nのカウントk
4.設定された場合に、このノードnがrを求めることを示すブーリアン
5.設定された場合に、このノードがrを有するが移送の途中であることを示すブールであり、この場合、ノード番号が新しいオーナーを特定する
いくつかの実施形態において、カウントkは、限りないリソースの追求に対処するために用いられる。kが閾値を超えた場合、システム周囲のリソースを追求するのではなく、新たに構築された継続を移動させる方がよいという決定がなされる。
以下は、リソースのマイグレーションを開始してリソースを受信するためのメカニズムの一例である。重要なトランザクションは以下を含む。
1.ノードnが、リソースrの要求をn’に送信する。
2.ノードn’は、リソースrの要求をnから受信する。
3.ノードn’は、特定の状況下でnに「拒否」メッセージを送信してよく、そうでなければ、「受け入れ」ることができ、リソースrを送信する。
4.ノードnは、リソースrがこの時点でn’によって送信不能である場合、n’から「拒否」メッセージを受信する。rがn’によって必要とされているか、または、要求の到着時にrがどこか他の場所に移送されている場合がありうる。要求が拒否された場合、n’は、リソースを移送する先のノードの「移送先」アドレスを送信できる。移送先アドレスがn’自体である場合があり、これは、「後に再試行する」ことと等価である。ノードnは、拒否メッセージを受信すると、n’によって示唆されたノード(しばしば、リソースの新しいオーナー)へ要求を再送信できる。nがシステム周囲のリソースを追求することを避けるために、nは、リソースを得るための試行の回数を記録することができ、試行の回数が閾値を超えると戦略を切り替える。
5.ノードnは、n’がリソースを送信できる場合、リソースrを受信する。この場合、nは、cが再開されうるように、rを待っていた継続cをスケジューリングする必要がある。
タイダルツリーのルート
いくつかの実施形態において、システム内のノードセットの内の1つの物理ノードが、「マスタノード」に指定される。このノードは、起動時に、初期仮想リソースマップおよびその他のデータ構造を構築し、他のノードにそれらを複製し、オペレーティングシステム(例えば、Linux)を起動する責任を有する。マスタノードは、1つの例外を除いて、システムが起動された後には任意の他のノードと同様でありうる。少なくとも1つの物理ノードが、タイダルツリーのルートを格納する必要がある。マスタノードは、ルートが配置されうる場所の一例である。タイダルツリールートスケジューリングオブジェクトのイベントキューの更新が、更新を実行するためにマスタノードへメッセージを送信することによって、各ノードにおいて処理される。
時間と共に、オペレーティングシステムおよびアプリケーションのリソースアクセスパターンが許す場合には、ハイパーカーネルが適合され、ローカル性が連続的に改善する。
継続
上述のように、全ノードにわたる物理メモリアドレスは一意的ではない。いくつかの実施形態において、継続内に物理メモリアドレスを含めることは、パーティション整数インデックスを用いてハイパーカーネル内の重要なデータ構造を指定することによって避けることができる。アドレスが継続内に入れられる必要がある場合、そのアドレスは、ソースの物理アドレスであり、宛先における物理アドレスとの関係性がないので、移動に注意が払われる。継続の移動は、上述のように宛先ノードにそのコンテンツをコピーして、ソースからターゲットへ任意の物理アドレスを再マッピングすることを意味する。
タイムスタンプ
いくつかの実施形態では、フリーランニングカウンタへのアクセスが、すべてのノードに可視である。これがない場合、各ノード上のフリーランニングカウンタも利用できる。継続内のカウンタが、ソースと宛先との間でマッピングされる。
ディスクおよび永続性フラッシュの取り扱い
必要とされるリソースがディスク(または永続性フラッシュ)上にある場合、いくつかの実施形態において、かかるリソースは、RAMなどのリソースよりも重い重力場を有するものとして扱われる。したがって、ディスク/フラッシュリソースは、あまり頻繁には移行しない傾向にある。その代わり、継続が、需要に基づいて、必要とされる永続性ストレージを含む物理ノードへ、または、永続性ストレージに関連するバッファへ、より頻繁に移行する。
オペレーティングシステム構成
オペレーティングシステムを構成する多くの方法がある。サーバについて、そのオペレーティングシステムが、ハイパーカーネルによって実装された仮想マシンから小さいセットのリソースタイプ、線形ブロック配列、ネットワーク、プロセッサ、メモリ、および、ノード間相互接続を含むストレージ、のみを必要とするよう構成されていると仮定できる。結果として、オペレーティングシステムのインストールの複雑さを軽減できる。
データ構造および関数の例
以下のセクションは、様々な実施形態で用いられるデータ構造および関数の例のリストを提供する。
init−continuation:計算がストールした時に、継続を開始する。
assignProcessor:(可能であれば)シャドープロセッサに新たな継続を割り当てるルーチン。
on−stall(r):リソースrについてストールイベントが起きる。
migrate−computation(computational−state,r,n):リソースrを有すると期待する別のノードnへの計算状態の移動を要求するためのメッセージ。
on−interrupt(i):ソフトウェア割り込みiが起きる。
handle−event(e):ハイパーカーネルが非同期的イベントを処理するよう要求された時に実行されるルーチン。
request−resource(r,n):ノードnからのリソースrの移送を要求する。
initiate−send−resource(r,n):ノードnへのリソースrの送信を開始する。
on−request−transfer−response(r,n,b):nからのrの移送要求が受け入れられたか拒否されたか。拒否された場合、bはtrueである。
on−transfer−requested(r,m):mからのリソースrに対する要求を受信する。
on−resource−transferred(r,n):リソースrの肯定応答がnから受信された。
on−receive−resource(r,n):リソースrがnから受信された。
migration−continuation(r):リソースの移動よりも継続の移動の方が良い場合かつその場合に限り、trueになる。
parent(s):スケジューラオブジェクトsの親スケジューラオブジェクトを返す。
cost(s,c):スケジューラオブジェクトsの待機キュー内の継続cの配置を評価するために用いられる。
find−best−within(s):スケジューラオブジェクトsの待機キューに格納された継続を返すコスト関数。
conserve−energy:低電力モードに入る。
resume−continuation(c):その時点でこの関数を実行しているプロセッサ内のcによって表された計算を再開する。
valid(i):割り込みiがまだ有効である場合かつその場合に限り、trueを戻すブール関数。
initialize(best−guess):コスト変数の最良推定を開始する。
insert−queue(s,c):スケジューラオブジェクトsの待機キューに継続cを挿入する。
return−from−virtual−interrupt:割り込みにより一時的に停止された実行を再開する。
r.owner:リソースrがローカルであるノードを返す。
r.e:リソースrがこのイベントを待っている。
e.r:このイベントはリソースrのためのものである。
e.continuation:このイベントが起きると、継続を再開する必要がある。
get−state():プロセッサの状態を返す。
scheduler−object(p):プロセッサpと現在関連しているスケジューラオブジェクトを返す。
on-request−transfer−response(r,m, response):リソースrをノードmから移送する要求への応答。応答は、「拒否される」場合のtrue、または、「受け入れられる」場合のfalseのいずれかでありうる。
ルーチンの例
以下は、様々な実施形態で用いられるルーチンの擬似コードの例である。以下では、「on−」で始まる関数は、非同期的イベントまたは入ってくるメッセージである。
==========================
init−continuation(computational−state)
==========================
/*ヒントhを持つリソースrを待っているプロセッサpによるInitContinuation*/
c=allocate continuation
c.state=computational−state
c.last=scheduler−object(p)
c.state=waiting−for−event
c.hints=h
e=allocate event in event−table
e.resource=r
e.continuation=c
return c
end InitContinuation
==========================
assignProcessor
==========================
/*物理ノードn内のプロセッサpがシャドープロセッサになると、そのO/Sのアイデンティティを放棄し、実行を再開するための継続を探し始める。pは、以下のように待機キューでかかる継続を探す:*/
s=scheduler−object(p)
initialize(best−guess)
best−s=nil
/*上方へトラバースして、最良の候補を追跡する*/
/*ルートのローカルにキャッシュされたコピーがあると仮定する*/
repeat
guess=cost(s)
if guess>best−guess
then
best−guess=guess
best−s=s
s=parent(s)
until s=nil
if best−s<>nil
then
c=find−best−within(best−s)
resume−continuation(c)
else conserve−energy
end assignProcessor
==========================
on−stall(r)
==========================
/*OnStallは、ハードウェアが仮想構成と物理構成との間の不一致を検出した時に呼び出される。より具体的には、ハードウェアがノードn上で見つけることができないリソースrを、ノードnが要求する。*/
if migration−continuation(r)
then
/*ノードnに計算を送信する*/
nn=owner(r)
/*ノードnは、リソースがおそらくノードnnにあると考える*/
migrate−computation(r,nn)
else
/*リソースrを要求する*/
c=init−continuation(get−state())
/*ローカルイベントテーブルにcを挿入するためのコードをここに挿入する*/
request−resource(r,owner(r))
assignProcessor/*この時点で、pは匿名のシャドープロセッサである*/
/*pは、実行すべき何らかの作業を見つける必要がある*/
end OnStall
==========================
on−migrate−computation(computational−state,r,n)
==========================
/* リモートノードは、継続を受信するためのメッセージをnから得る。注:この場合のcは、継続のコンテンツであり、継続自体ではない。*/
c=InitContinuation/*要求内の情報を用いる*/
c.state=computational−state
e=insert c into the local event−table
handle−event(e)
end on−migrate−computation
==========================
on−interrupt(i)
==========================
/*(物理ノードnのサブツリー内の)プロセッサpが(特定のハードウェア設計に特有の非常に低レベルのメカニズムを用いて)iによって割り込まれた時、pは、以下の通りにする:*/
while valid(i)
e=event−table(i)/*iに対応するイベントを見つける*/
handle−event(e)
i=next−queued−interrupt
end while
/*前の実行を再開する*/
return−from−virtual−interrupt:
end on−interrupt
==========================
handle−event(e)
==========================
/*イベントが発生した。イベントテーブルから最良のスケジューラオブジェクトへそのイベントを移動させる。*/
c=e.continuation/*イベントeのための継続を見つける*/
event−table(i).clear=true/*テーブルからイベントを除去する*/
e.complete=true/*eを完了としてマークする*/
c.state=ready
/*ここで、cを置くのに最良の場所を見つける*/
s=c.last
initialize(best−guess)
/*最良の選択を探す*/
/*ルートのローカルにキャッシュされたコピーがあると仮定する*/
repeat
guess=cost(s,c)
if guess>best−guess
then
best−guess=guess
best−s=s
s=parent(s)
until s=nil
insert−queue(best−s,c)/*最良のsの待機キューにcを入れる*/
end handle−event
==========================
request−resource(r,n)
==========================
/*ノードnが、ノードn’によって所有されるリソースrを必要とする場合、そのリソースは要求されるが、他の誰かが先を越して要求した可能性があるか、または、n’が現在それを利用しているために、その要求は満たされない場合がある。*/
current−resource−map(r).wanted=true
request−transfer(owner(r),r)/*rのオーナーに要求を送信する*/
/*rの移送を要求する*/
return
==========================
on−request−transfer−response(r,m,is−rejected)
==========================
/*ここで、あなたがリソースrについてのノードへの以前の要求からの応答を得るノードであることを考慮する。この要求への応答が来ると、それは、受け入れられるかまたは拒否されうる。*/
if is−rejected
then/*リソースがmに移送された*/
increment k
if k>threshold
then
/* あなたは永久に追求したいとは思わない*/
/* リソースを得ようとする。諦める*/
migrate−computation(r,m)
return
else
request−transfer(r,m)/*再試行する*/
return
else
/*要求が拒否されなかった。rはリソースである */
r.k=0
r.wanted=false/*リソースが移動された*/
r.owner=me/*オーナーをn(すなわち、「私」)に設定する*/
if the resource is memory,
update the hardware memory map with the new memory
return
==========================
on−transfer−requested(r,n)
==========================
/*rへのリソース要求がノードnから来た時、オーナー(r)にとって移送が進行中であれば、要求を拒否する*/
if r.being−transferred
then
send−request−response(r,owner(r),true)
else
/*リソースの移送が受け入れられる*/
r.transferring=true
initiate−send−resource(r)
if type(r)=memory
then update local memory map
send−request−response(r,owner(r),false)
return
==========================
on−resource−transferred(r,n)
==========================
/*移送が完了した旨の肯定応答が来た時*/
r.owner=n
r.transferring=false
return
==========================
on−receive−resource(r,n)
==========================
/*ここで、要求されたリソースrを伴うメッセージをnから受信する*/
r.k=0
r.wanted=false/*それが求められていることを示すビットをクリアする*/
r.owner=me/*オーナーをn(すなわち、「私」)に設定する*/
if the resource is memory,
update the memory map with the new memory
send−resource−transferred(r,n)
handle−event(r.e)/*待っていたイベントが発生した*/
return
ワーキングセットおよびスレッドの関連付け
ここまで、様々な実施形態が、緊密に相互接続された1セットの物理サーバ(またはコンピュータ)にわたって分散された仮想サーバ(またはコンピュータ)のインスタンスを生成、管理、および、最適化する方法が示された様々な実施形態について説明した。
かかるシステムを効率的に動作させるために、ゲスト物理プロセッサ(vcpu)のセットが、メモリの仮想ページ(ゲストオペレーティングシステムが物理ページであると考えるメモリのゲスト物理ページ)のセットに関連付けられ、その結果、それらは、1セットのコンピュータ(例えば、クラスタ内のノード)にわたって同じ場所に配置されうる。同じ場所に配置されると、マイクロプロセッサ内の仮想化ハードウェアを用いて、ハードウェアベースの非仮想サーバと一致したパフォーマンスレベルを達成することができる。
vcpuによるゲスト物理メモリページのセットへのページアクセスのパターンは、アプリケーションプログラム、オペレーティングシステム、ネットワーク、リアルタイムイベント、I/Oデバイス、などの組みあわせによって規定され、真の仮想サーバが構築された場合には変化しない。
現代のオペレーティングシステム(Linux、FreeBSD、Windows、および、MacOSなど)は、「スレッド」と呼ばれる非同期的な制御構造を実施するための1セットの機能を提供する。スレッドは、オペレーティングシステム内のソフトウェア構造およびメカニズムもしくは非同期的かつ並行なプログラムの動作を可能にするランタイムライブラリ(もしくは両方)であり、しばしば、非同期割り込みへの応答を含む。スレッドは、サブプログラムが、異なる時刻に異なるデータアクセスパターンを持つ異なる命令ストリームを実行することを可能にする。本明細書に記載の例において、スレッドは、ゲストオペレーティングシステムにおいて動作するスケジューラの制御下で、1セットの仮想プロセッサにバインドされてよい。任意の所与の時点に、スレッド(例えば、ゲストオペレーティングシステム上で動作するアプリケーションに関連付けられているゲストスレッド)が、vcpu上で動作しているか、または、全く動作していない。その後に、スケジューラは、異なる物理プロセッサ上でそのスレッドを実行すると決定してよい。
上述のように、仮想環境内のvcpuが、仮想マシンおよび仮想マシンのスケジューラ(ゲストオペレーティングシステムスケジューラとは異なりうる)の実施中ずっと、真の(「ホスト」とも呼ばれる)物理プロセッサにバインドされてよい。
現代のオペレーティングシステムは、しばしば、所与の時点にどのスレッドがどのvcpuで動作しているかに関してハードウェアまたは仮想化システムに情報を提供しうる。
オペレーティングシステムがシステムのすべてのリソース(例えば、メモリ、I/O、ネットワークなど)への直接かつ高速なアクセスを有するという仮定が、オペレーティングシステムによってなされる。本明細書に記載の技術を用いて構築された1セットのノードにわたる単一の仮想マシンにおいて、この仮定はセマンティック的には維持されるが、物理的現実は当てはまらない場合がある。例えば、非ローカルリソースにアクセスする仮想プロセッサ(またはスレッド)が存在する場合があり、ここで、この非ローカルアクセスは、直接アクセスでも高速アクセスでもない。上述のように、仮想化システムが物理的に実現可能ではないゲストからのイベントを観察すると、ストールが引き起こされる。仮想化システムは、ストールを引き起こした状況を修正するかまたは他の方法で対処することで、ゲスト(オペレーティングシステム)によって予測されたセマンティック動作(semantic behavior)とその状況を一致させるように動作する。仮想システムのパフォーマンスは、ゲストオペレーティングシステムのベースパフォーマンスによって支配されるが、ストールの数、および、ストールをセマンティック的に正確にするのに掛かる合計時間によって低下しうる。以下に述べる技術を用いると、ストールの数およびストールあたりの平均時間が、仮想化システムにおいて削減されうる。
ここまでに、仮想プロセッサおよび仮想ページセットの利用パターンを追跡するため、ならびに、仮想プロセッサおよび仮想ページを分散仮想環境を通して移動させることについて決定するための技術の例を記載した。上述の技術は、メモリのページセットにアクセスするスレッドセットのアクセスパターンを追跡するために、改良および拡張もしくは他の方法で適合されてよい。
スレッドと、メモリの関連ページセットとの追跡は、仮想プロセッサおよびメモリページセットのアクセスのパターンが、実際には、ゲストオペレーティングシステムスケジューラの制御下で仮想プロセッサ内で動作するゲストスレッドによって決定されるという観察に基づきうる。ゲストスレッドは、異なる仮想プロセッサ、したがってホスト物理プロセッサで、異なる時に動作しうる。vcpu、したがってホスト物理プロセッサは、異なる時点に同じゲストスレッドを実行してよい。
ホスト物理プロセッサへのスレッドのバインディングは、様々な要因に依存し、要因は、ゲストスケジューラのプログラムされた動作、スレッドによって実行される計算、外部の非同期イベントのパターン(ネットワークパケットの到着など)、I/O割り込みの完了、などを含みうる。これらのイベント、したがってイベント到着のパターンおよびゲスト物理プロセッサへのゲストスレッドのバインディングは、事前に予測可能ではない場合がある。したがって、システムの動作は、プログラムの実行が決定論的である場合でも、非決定論的でありうる。
スレッドの検査によって、どのスレッドがどのvcpuにおいて動作しているのかは知りえない。なぜなら、これは、ゲストオペレーティングシステムまたはゲストランタイムライブラリの制御下にあるからである。しかしながら、後に詳述するように、オペレーティングシステムは、任意の所与の時点にどのスレッドが各仮想プロセッサで実行しているのかを決定するための様々なメカニズム(またはヒント)を提供する。かかる情報は、仮想プロセッサ(vcpu)のための基本的なスケジューリングおよびマイグレーションの決定に用いられてよい。後に詳述するように、本明細書に記載の技術を用いると、(ゲストスレッドを実行する)仮想プロセッサは、できる限り、同じノード上の仮想メモリ(ゲスト物理メモリ)の適切なページセットと共に一緒に維持されうる。そうすることにより、非ローカルアクセスによるストールを削減すると共に、実際の物理コンピュータに匹敵するパフォーマンスレベルを達成できる。さらに、オーバーヘッド(例えば、ストールの回数およびストールあたりの平均時間の積)も小さくなりうる。これは、最もストールしそうにない場所にページおよびスレッドをインテリジェントに配置することによって達成されうる。ページ転送およびページマイグレーションの回数も、最小化されうる。
読み出される必要があったために、ページがノード上に存在する場合がある。そのページは、書き込まれる必要があったために、ノード上に存在する場合もある。いくつかの実施形態において、複数のノードがすべて、ページを読み出している限りは、それらのノードは、ページのローカルコピーを有しうる。ページが書き込まれる必要がある時、更新/書き込みを行うノード以外のノード上のそのページの全コピーに無効化が実行される。いくつかの実施形態において、更新が完了すると、他のノードは、ページが再び読み込まれる必要があった場合にページのコピーを求めてよい/要求してよい。
スレッドと参照ページのセットとの間の関係性を管理するための技術について、以下で詳述する。ページpを所与として、本明細書に記載の技術を用いると、どのスレッドがpに対する強い必要性を有するのかが決定される。さらに、スレッドtを所与として、どのページがtによって強く必要とされるのかが決定される。一例として、スレッドがvcpuで実行している時、スレッドが実行しているノードに存在しないページを参照しているために、スレッドがストールした場合、ページが到着するまでストールが実行される。ストールは、このスレッドがこのページを必要としていることを示唆するものである。かかる情報は、スレッドが動作しているノードがどれであっても、例えば、ページへのアクセスを得るために所与のスレッドストールの回数の頻度をカウントすることによって記録され、そして、管理されてよい。スレッドによって必要とされると決定されたページは、スレッドに関連するページのワーキングセットに含められる。任意の所与の時点にどのスレッドが各仮想プロセッサを実行しているのかを決定するためのメカニズムまたはヒントをオペレーティングシステムが提供しうるので、スレッドは、スレッドレベルに基づいて追跡または識別されうる。
図13Aは、スレッドおよびワーキングセットが関連付けられた環境の実施形態の一例を示す。以下に記載の技術を用いて、所与のゲストスレッドにとって最も関心のあるページが決定されてよい。仮想システム内の各ゲスト物理ページについて、所与のページに最も関心を持つスレッドが決定されてもよい。以下に記載する実施形態の例は、Intel仮想化ハードウェア(例えば、Intel VT−x)を含むが、本明細書に記載の技術は、任意のタイプの仮想化ハードウェア(例えば、AMD AMD−V)に対応するよう様々に適合されてよい。
図13Aの例では、ゲストアプリケーション1302が、ゲストオペレーティングシステム1304の上で動作しており、ゲストオペレーティングシステム1304は、企業向けスーパーコンピュータ(例えば、システム100)を形成する一連の個々の物理ノード1306にわたって集合的に動作している。より具体的には、ゲストオペレーティングシステムは、図4Bに関して説明するように、一群のハイパーカーネルによって定義された仮想環境上で動作している。
図7に関して上述したように、ゲストオペレーティングシステムの視点から、ゲストオペレーティングシステムには、複数の「仮想化プロセッサ」(本明細書では「仮想プロセッサ」または「vcpu」とも呼ぶ)が見えており、複数の仮想化プロセッサは、企業向けスーパーコンピュータに含まれるすべてのノードにわたるハイパースレッドの総数に対応する。オペレーティングシステムには、すべてのノードにわたる物理メモリの総量に等しいサイズの大型の物理的な線形メモリのように見える「仮想化物理メモリ」(本明細書では「ゲスト物理メモリ」とも呼ぶ)も見える。かかる仮想構成において、ゲストの視点からのすべてのメモリアドレス(本明細書では「gpa」の「ゲスト物理メモリ」とも呼ぶ)は、(グローバルに)一意的であり、企業向けスーパーコンピュータを形成するノードに含まれるすべてのメモリの合計を表す。gpaは、(ノードに関わらず)クラスタ全体にわたって一意的であり、ここで、ゲスト物理アドレス空間は、ゲストオペレーティングシステム(ゲストOS)によって定義された広いフラットアドレス空間である。
図13Aの例において、ゲストアプリケーション1302は、仮想アドレス空間に関連付けられている。例えば、ゲストオペレーティングシステム1304がゲストアプリケーション1302を立ち上げると、ゲストOSは、そのアプリケーションのための仮想アドレス空間を生成(例えば、ページテーブルを設定)する。ゲストアプリケーションが実行されるごとに、新たなページテーブルが生成される。ゲストアプリケーション1302は、1セットのスレッドも有する。この例において、ゲストアプリケーション1302は、シングルスレッドであり、シングルスレッド1308(本明細書では「ゲストスレッド」とも呼ぶ)を有する。他のアプリケーションが、複数のスレッドを有してもよい(すなわち、アプリケーションは、マルチスレッドであってもよい)。この例において、ゲストスレッドは、vcpu上で実行中である。vcpuは、企業向けスーパーコンピュータの物理構成におけるハイパースレッドなど、物理ノード上の物理プロセッサ(本明細書では「pcpu」とも呼ぶ)上で動作する。ゲストスレッドは(vcpuと同様に)、クラスタにわたってグローバルに一意的である。
ゲストアプリケーション1302が動作している時、ゲストスレッドは、アプリケーションの仮想アドレス空間内の仮想ページへの参照を行う。ゲストアプリケーションによって参照される(そして、計算を継続するためにゲストスレッドによって必要とされる)メモリの物理ページを取得するために、動的アドレス変換の2つのレベルが仮想環境内で実行される。動的変換の2つのレベルは、仮想化をサポートするプロセッサのために仮想化を有効にすることによって自動的に実行される(すなわち、仮想化が有効にされると、アドレスが参照される度に、2段階のアドレス変換が実行される−仮想化システムが実行されていない場合、アドレス変換の第2レベルは実行されない)。
図13Bは、仮想環境における動的アドレス変換の一例を示す。この例において、アプリケーションレベルでは、ページアドレス変換の第1レベルが、(ゲストオペレーティングシステムによって管理される)第1レベルページテーブル1310を用いて内部vcpu状態によって実行され、第1レベルページテーブル1310は、(メモリのページのための)仮想メモリアドレス1312をゲスト物理アドレス1314に変換する。いくつかの実施形態において、第1レベルページテーブルは、様々なエントリを含むメモリのブロックであり、ここで、第1レベルページテーブルは、ゲストオペレーティングシステムによって書き込まれ、ハードウェアによって読み出される。異なるアプリケーションが、2つの異なる仮想アドレス空間内で動作する(そして、ゲストレベルで、各アプリケーションは、それぞれの仮想アドレス空間の各々をゲスト物理メモリ/アドレス空間に対応付ける独自の第1レベルページテーブルを有する)。例えば、仮想メモリアドレスは、対応するゲスト物理アドレスを取得するために、第1レベルページテーブルへのインデックスとして用いられる。したがって、仮想アドレスは、ゲストオペレーティングシステムが「物理アドレス」であると考えるもの(ただし、実際には、ハイパーカーネルの視点からはゲスト物理アドレスである)に変換されている。
次いで、第1レベルページテーブルのルックアップに応答して返されたゲスト物理アドレス(または、例えば、64ビット値であってよいgpaのブロック)は、メモリの対応する物理ページ(例えば、4K物理メモリアドレス)を取得するために、物理プロセッサの仮想化ハードウェアによって、第2レベルページテーブル1316へのインデックスとして用いられる。第2レベル変換テーブルは、ゲスト物理アドレスを「実」物理アドレス1318(クラスタのノードに存在するメモリの実物理ページ)に対応付けるために、ハードウェア内に設定されてよい。ゲストOS上で動作する各アプリケーションは、独自の第1レベルページテーブルを有するが、第2レベルページテーブルは、ゲストオペレーティングシステムが物理メモリであると考えるもののメモリの同じプールの外で動作する。
第2レベルページテーブルは、各ノードに固有であり、ここで、企業向けスーパーコンピュータ内の各ノードは、対応する第2レベルページテーブルに関連付けられている。各ノードは、その独自の対応する第2レベルページテーブルに関連付けられているが、ページテーブルはすべて、ゲスト物理アドレスを用いて同様にインデックス化されてよく、ゲスト物理アドレスは、上述のように、スーパーコンピュータクラスタにわたってグローバルに一意的である。ゲスト物理アドレスに対応するメモリのページがノード上に存在する場合、ノードの第2レベルページテーブル内に対応するエントリがあることになる。
図13Cは、第2レベルアドレス変換の実行の実施形態の一例を示す。この例では、第2レベルページテーブル1316をインデックス化して、対応する4K物理メモリアドレス1318を取得するために、(後に詳述する)vcpu状態のCR3レジスタに格納されたゲスト物理アドレス(1314)が用いられ、アドレス1318は、vcpuのアイデンティティを担ったpcpuが存在するノード上の物理メモリ1320の実ページを指し示す。この例において、要求されたページは、ノードにローカルであるので、ゲスト物理アドレスに対応する第2レベルページテーブル内に有効なエントリが存在し、その後、実物理メモリのページが、ゲストスレッドによって取得および利用されうる。
ゲスト物理アドレスに対応するメモリのページがノードにローカルではない場合、ノードの第2レベルページテーブルは、ゲスト物理アドレスのためのエントリを含まない(ここで、例えば、エントリは、ゼロアウトされるか、または、無効化されている)。したがって、参照されたゲスト物理アドレスに対応する実物理ページがノードでローカルに利用可能ではないと判定されうる。ページは、ある時点でノードにあり、ハイパーカーネルによって別のノードにマイグレートされたか(この場合、ページの位置が追跡される)、または、ノード上には全く見られなかったか(例えば、仮想化システムが新たに起動される場合がある)、のいずれかである。ページがノードからマイグレートされた場合、プロセッサが、そのノード上の物理ページをルックアップしない(そのページは、どこか他へ移動しているため)ように、第2レベルページテーブル内のエントリは、ゼロアウトまたは無効化されている。
上述のように、メモリのページがアクセス可能ではないためにストールイベントが発生すると、必要とされたページが、そのメモリの必要とされるノードへマイグレートされてもよいし、vcpuがマイグレートされてもよい。ページが移動される場合、そのコンテンツが移動され、これは、宛先ノードで物理ページを割り当て、新しいノードにページのコンテンツをコピーすることを含む。宛先上の第2レベルページテーブルも、gpaに対応するエントリが新たにマイグレートされた物理ページで埋められるように更新されている。したがって、次にページが参照された時、障害は引き起こされない。vcpuがマイグレートされる場合、それは、参照されたメモリのページを有するノード上に再構築される。ゲスト物理アドレスは仮想化システムにわたってグローバルに一意的であるので、マイグレートされたプロセッサがその新たなノードの第2レベルページテーブルにアクセスすると、有効なエントリが、参照されたgpaに対応して見いだされる(すなわち、ノード上のすべての第2レベルページテーブルへのインデックスが、グローバルに一意的なgpaによってインデックス化されるので、同一または一定である)。
したがって、アドレス変換の2つのレベルを実行することにより、ゲストスレッドによって参照された仮想アドレスは、ゲスト物理アドレスに変換され、次に、ゲスト物理アドレスは、実物理アドレスに変換される(メモリの参照されたページが、メモリのページにアクセスしたゲストスレッドを実行中のvcpuを実行しているpcpuと同じノード上にある場合)。要求された実ページがそのノード上にある場合、それは、第2レベルページテーブル内にあり、ストールは発生しない。メモリの実ページはアクセスされ、ゲストスレッドは、その処理を継続してよい。
しかしながら、ゲストスレッドによって必要とされるゲスト物理アドレスに対応するメモリの実物理ページが、ゲストスレッドの現在実行しているノードにローカルではないと仮定する。ここで、ゲスト物理アドレスに対応するエントリは、第2レベルページテーブル内に存在しないか、もしくは、無効であるかゼロアウトされている。
この例では、マシン障害が生じる、すなわち、ストールイベントが発生する。ストールの時点で、ゲストスレッドを実行中のvcpuは、pcpuで実行していた。したがって、pcpuはストールすることになる。この結果、割り込みが生じる。この割り込みは、ハイパーカーネルを指し示す割り込みベクトルを経由する。割り込みは、ハイパーカーネルによってキャプチャされ、ハイパーカーネルは、1セットのルーチンを実行する。この例では、ルーチンの実行により、pcpuの状態が保存される。一例として、ストールが発生すると、物理プロセッサ状態のブロックを取得する命令が実行される。物理プロセッサ状態の状態は、物理プロセッサがそのアイデンティティを担ったvcpuの状態に対応する(ここで、ハイパーカーネルは、仮想プロセッサに対する物理プロセッサの対応付けを維持しており、したがって、特定のvcpuの識別子に物理プロセッサの状態を対応付けてよい)。プロセッサの状態のブロックは、メモリの領域に保存される。物理プロセッサブロック状態を保存する機能は、マイクロプロセッサハードウェアアーキテクチャによって(例えば、ハードウェアによって提供されるマクロによって)提供されてよい。この例において、状態情報の保存は、ハードウェアアーキテクチャによって提供されたハイパーバイザによって提供されるソフトウェア命令であり、これは、物理プロセッサ上での多重化を維持/追跡する。
一実施形態において、保存されたプロセッサ状態は、上述のように、継続が作成された時に保存されたvcpuの状態である。プロセッサ状態は、様々なレジスタ、プログラムカウンタなどを含んでよい。ストール中、呼び出された1セットのルーチンは、vcpuで動作しているゲストスレッドのアイデンティティおよび/またはゲストスレッドによって参照されたゲスト物理アドレスのアイデンティティを決定するためにも用いられる。例えば、後に詳述するように、識別は、ストール中に保存されたプロセッサ状態内の特定のレジスタにアクセスすることによって実行されてよい。したがって、物理プロセッサが何を実行していたのか(これは、ゲストスレッドだったであろう)、および、プロセッサがメモリにアクセスを試みていた時にどのページテーブルを利用していたのかが、決定され記録されてよい。かかるアイデンティティ情報を取得することにより、スレッドとメモリのページとの間の関連が決定されてよい。
スレッドアイデンティティの決定
上述のように、(pcpu上で動作している)vcpuのプロセッサ状態が保存される。この例において、(物理プロセッサがそのアイデンティティを担った)vcpuで実行しているゲストスレッドのアイデンティティが、以下のように決定される。FS−Base0レジスタ内の値が取得される。
ゲストオペレーティングシステムにおいて、各スレッドは、(スレッディングライブラリによって導入されうる)所与のスレッドに固有のスレッドローカルストレージを備えるメモリまたはデータ構造の領域を確保させる。FS−Base0レジスタ値は、特定のスレッドのためのスレッドローカルストレージへのポインタを含む。スレッドローカルストレージは、カーネル情報に関連付けられてもよい。FS−Base0レジスタは、ゲストオペレーティングシステムによって管理される。
FS−Base0レジスタ値は、2つの異なるスレッドが異なるFS−Base0値を有するように設定される(すなわち、スレッドT2と等しくないスレッドT1について、スレッドT1のFS−Base0は、スレッドT2のFS−Base0と等しくない)。したがって、fsbaseレジスタ内の値は、vcpuで実行中のゲストスレッドを一意的に識別するために用いられてよい。
ゲスト物理アドレスの決定
ゲストスレッドによって参照されるゲスト物理アドレス空間は、保存されたプロセッサ状態の中のレジスタから取得されてよい。この例において、スレッドがストールしたページのgpaのアイデンティティは、プロセッサ状態の保存されたブロックの内部CR3レジスタ内の値にアクセスすることによって取得される。CR3レジスタ値は、アドレスをマッピングするためにゲストオペレーティングシステムによってどのテーブルが用いられていたのかを示しており、ここで、CR3レジスタ内の値は、アドレス空間(ゲスト物理アドレス空間)をゲストオペレーティングシステムによって見られる通りに定義する。例えば、CR3レジスタは、ノード上のゲスト物理アドレスすべてのための第2レベルページテーブルへのポインタを含んでおり、ここで、CR3は、特定のアドレス空間を参照する(新しいゲストアプリケーションまたはプロセスが実行されると、新しいCR3アドレス空間が生成される)。上述のように、第2レベルページテーブルは、gpaを実物理アドレスに変換するために用いられる。例えば、アドレス変換は、CR3レジスタ内のgpa値を用いて第2レベルページテーブルをインデックス化することによって、(特定のvcpuとしてのアイデンティティで)物理プロセッサによって実行される。一例として、CR3レジスタから取得されたゲスト物理アドレスの上位数ビットは、第2レベルページテーブルへのインデックスとして用いられる(例えば、CR3レジスタの上位20ビットは、第1ページディレクトリエントリの物理アドレスを格納するページディレクトリベースレジスタであり、ここで、CR3は、プロセッサが、仮想アドレス指定が有効である時に適切なページディレクトリおよびページテーブルをロケートすることによって、線形アドレス(gpa)を物理アドレスに変換することを可能にする)。上位数ビットは、より低位のビットをマスクして、より高位のビットを得ることによって取得されてよい。これら高位のビットは、ゲスト物理アドレスがどの4Kページを参照するのかを示す(必ずしもすべてのビットが必要とされうるわけではない)。第2レベルページテーブルは、ノードによって異なるが、gpasは、すべてのノードにわたって一意的であり、任意の第2レベルページテーブルへのグローバルインデックスとして利用できる。
上述のように、ページがノード上にある場合、要求されたページの実物理アドレスが返される(すなわち、CR3レジスタ値が第2レベルページテーブルをインデックス化するために用いられる時に、第2レベルページテーブル内に実物理アドレスに対応するエントリが存在する)。メモリのページがノード上に存在しない場合、ストールが発生する(CR3レジスタのインデックスにおけるエントリがゼロ化または無効化される)。
スレッドコンテキスト切り替え
上述の例では、メモリの要求されたページがノード上でローカルに利用可能である場合に、ストールが起こった。vcpuにおいて動作するゲストスレッドおよび/またはvcpuによって参照されたゲスト物理アドレス空間のアイデンティティが、ストールに応答して、保存されたプロセッサ状態のブロックから決定される。スレッド/ページの識別は、他のイベントに起因するストールが発生した時にも実行されてよい。例えば、ストールは、スレッドコンテキスト切り替えが起こった時にも呼び出されてよい。ゲストオペレーティングシステムが、スレッドコンテキスト切り替えを実行してよく、ここで、そのオペレーティングシステムは、ゲストスレッドを他のvcpuへ切り替え、移動、または、多重化する。vcpu内のスレッドが切り替えられると、これは、vcpuのFS−Base0レジスタ値の対応する変更を引き起こす(例えば、スレッドコンテキスト切り替えが発生すると、FS−Base0レジスタは、新たなスレッドに対応する新たな値に切り替えまたは更新される)。
ハイパーバイザは、vcpuコンテナ内で動作するスレッドのアイデンティティを決定するために、ゲストオペレーティングシステムで起こっていることをイントロスペクトしてよい。ハイパーバイザの一部が、pcpu上で実行された多重化を追跡するため、および、プロセッサ状態のブロックを維持するために、利用されてよい。例えば、スレッドの追跡は、上述のようなスレッドコンテキスト切り替えによるFS−Base0レジスタ値の変化など、内部レジスタの変化が起こった時に、ハイパーバイザにおいてキャプチャされてよい。いくつかの実施形態において、FS−Base0レジスタの変化が検出されると、ストールが呼び出され、その結果、ハイパーカーネルは、今や、vcpuが異なるスレッドを実行していることに気がついている。
例えば、ゲストオペレーティングシステムが特定のvcpuにおいて処理を実行していたと仮定する。ゲストOSは、その処理を別のvcpuへ切り替え、そのため、FS−Base0レジスタを更新する。FS−Base0レジスタの更新は、ストールをトリガし、ストールは、ハイパーカーネルをウェイクアップさせる。ハイパーカーネルは、FS−Base0レジスタの以前の値が何であったかを決定する、および/または、新しいFS−Base0レジスタ値を観察するよう構成される。かかる観察に基づいて、スレッドコンテキスト切り替えが特定されてよい。スレッドコンテキスト切り替えによって呼び出されたまたはトリガされたストールの間に、vcpu内の/vcpuによって参照されたスレッドおよび/またはメモリのページのアイデンティティが、上述のように決定されてよい。
カーネル/ユーザ空間
ゲストオペレーティングシステムが、ストールの時点でユーザ空間コードまたはカーネル空間コードのいずれかを実行していた場合がある。ゲストOSがユーザ空間コードを実行していた場合、FS−Base0レジスタは、上述のように、実行中であったゲストスレッドを指し示すように書き込まれる。
カーネルコードが実行されていた場合、特定の値(例えば、ゼロ)が、FS−Base0レジスタ内に入り、これは、(ゲストスレッド/ゲストオペレーティングシステムコードではなく)カーネル空間コードが実行されていたことを示す。例えば、ゲストオペレーティングシステムが、ユーザ空間内での動作からカーネル空間へ切り替わると仮定する。2つの空間の間の変化は、FS−Base0レジスタの変化につながり、これは、上述のように検出されうる。CR3レジスタも同様に変化し、カーネルアドレス空間を指し示しうる。
カーネル空間にある間にストールが発生した時に、スレッド/ワーキングセットのインサイト(洞察)が得られてもよい。一例として、カーネル空間への変化が、FS−Base0レジスタ値のゼロへの変化によって検出されると仮定する。CR3値が変化していない場合、物理プロセッサによって行われる作業は、一致するCR3値を有するスレッドに関連または起因しうる。したがって、(ユーザ空間内で動作する)ゲストスレッドによって行われる作業は、カーネル空間への切り替えが起きた時に決定されうる。したがって、ワーキングセットのインサイトは、カーネル空間内でもユーザ空間内でも、任意のストールで起こりうる。
(上述のように識別されてもよい)スレッドによってアクセスされたゲスト物理アドレスを決定することにより、スレッド間の関係性が決定されてよい。例えば、CR3レジスタ内のアドレスは、グローバルに一意的なゲスト物理アドレスであるので、2つのスレッドが同じCR3値を有する場合、それらのスレッドは同じゲスト物理アドレス空間内で実行している(例えば、2つのスレッドは、同じアドレス空間を共有している)と判定される。これは、2つのスレッドが密接に関連していること(例えば、同じページテーブルを共有する可能性があること)を示すものである。
したがって、上述の技術を用いると、どの特定のスレッドがどの特定のゲスト物理アドレス空間で動作していたのかが決定される。時間と共にストールイベントが起きると、スレッドによって参照されたメモリのゲスト物理ページのパターンまたはセット(すなわち「ワーキングセット」)が識別または他の方法で決定されてよい(ここで、メモリアクセスのパターンは、スレッド依存か、vcpu依存かである)。したがって、各スレッドについて、所与のスレッドにとって関心のあるページが決定されてよい。さらに、各ページについて、所与のページに関心のあるスレッドが決定されてもよい。
履歴の記録
ストールされたvcpuに関連するゲストスレッドおよび/またはゲスト物理アドレスの識別後、識別された情報は、履歴に記録されてよい。所与のスレッドについて、スレッドによってアクセスされたページが記録される。所与のページについて、ページにアクセスするスレッドが記録される。いくつかの実施形態において、ゲスト物理ページがゲストスレッドによってアクセスされた各時刻が記録される。アクセスは、ヒット(ページがローカルに利用可能であった場合)またはミス(ページが非ローカルであった場合)のいずれかの結果になりえた。ページアクセスがヒットであったかミスであったかにかかわらず、ゲストスレッドによってアクセスされたページの識別子が記録される(すなわち、ヒットおよびミスの両方が記録される)。アクセスに関連付けられているタイムスタンプが、履歴情報の一部として記録されてもよい。履歴は、時間と共に更新されてよい。例えば、仮想化マシンによって実行される処理が進むにつれて、計算の状態ならびにスレッドおよびメモリのメモリアクセスパターンの状態が変化し、経時的に進展する。したがって、スレッドとワーキングセットとの間の関連付けは、経時的に動的に変化しうる。
メモリとスレッドとの間の関係性を特徴付ける情報は、後に詳述するように、メモリハウスキーピング、タイダルツリー意思決定、コスト関数決定、リモートノードからのリソース要求の受信など、ハイパーカーネル内のいくつかの場所で用いられてよい。
いくつかの実施形態において、スレッドとページとの間の関係性が、評価および維持され、これらの関係性を意思決定で最大限に利用するハイパーカーネル動作を導くことを可能にする動作を有するAPIが設計される。
以下では、本明細書に記載の仮想化システムの処理において決定するために利用できるコスト項およびメトリックの例のリストである。コスト項がどこでどのように(例えば、ハウスキーピング、タイダルツリー決定、ペアワイズリソースマイグレーションネゴシエーションなどにおいて)利用されるのかについてのさらなる詳細については後述する。
メモリ状態
いくつかの実施形態において、所与のスレッドT、ノードn、および、時刻tについて、Tが時刻tの前の或る期間中にそのノードで実行していたと仮定して、Tがその期間中にノードn上でアクセスしたページHのセットが記録される。記録されたページのセットは、時刻tでのnにおけるTのページアクセスH,t,Nの履歴と呼ばれる。実際には、H,t,nは、Tが、ある持続時間δについて、期間[t−δ,t]中にn上でアクセスしたすべてのページの合理的なサブセット近似を表しうる。いくつかの実施形態において、ハードウェアのサポートがなければ、非常に大量のオーバーヘッドを起こすことなしにスレッドのアクセスを一つ一つ記録することは、計算的に困難でありうるので、この近似が利用される。ハードウェアのサポートが利用可能である場合、それは、スレッドアクセスを記録するために用いられてよい。いくつかの実施形態において、一定ではないデルタを参照するのではなく、上述の時間は、可変長の区間に関して表されてよい(例えば、[t1・・・t2]または[t3・・・t4])。
温かさ(warmth)および利用度
各履歴H、t、nについて、2つのメトリック(利用度および温かさ)が保持される。いくつかの実施形態において、利用度(適合度と呼んでもよい)は、過去の或る時点に記録された履歴H、t、nを、より近い過去[t’−δ’,t’](ここで、現在時刻t’>tであり、或るδ’の間の区間)で起きたゲストスレッドTのページアクセスの最新パターン(すなわち、その新たな履歴H、t’、n)に関連付ける。t’およびtでの2つの履歴に記録されたアクセスが同様である(すなわち、先に時刻tで記録された履歴が繰り返されている)場合、ページH,t,nのセットのTによる利用度は高いと決定される。一実施形態において、利用度は、最近の重複におけるページの再利用度として、または、2つの履歴/期間の間でのページアクセス動作の重複の量として計算される。
いくつかの実施形態において、温かさは、履歴H,t,n内のどれだけのページが現在時刻t’>tにおいてノード上でまだローカルであるのかを測る。そのため、この例において、スレッドの履歴の温かさは、ノード上でまだローカルであるページのセットに履歴を関連付ける。一実施形態において、温かさは、ノード上でまだローカルであるページのアクセスの割合または比率として計算される。これは、最近アクセスされたページの内、どれだけのページがノード上にまだ存在するすなわちローカルであるのかを示す。一例として、最近のある期間中にノード上のゲストスレッドによってアクセスされたページの内の80%が現在ノード上からなくなっていると判定されたとする。その結果、現在時刻における温かさは、20%と計算される。
利用度は、Tがアクセスしていると共にその履歴H,t,nにも存在するページの割合の推定に基づいて、スレッドTが現在動作しているノードnで更新される。しかしながら、本明細書に記載するように、温かさは、例えば、現在Tの履歴内にあるページが除去された場合に、(Tが現在動作しているノードとは無関係に)ノードnで更新される。各スレッドTについて、温かさおよび利用度は両方とも、Tの履歴H,t,nが格納されるローカルノードnに関して計算されるため、温かさおよび利用度を計算するために必要になりうるパラメータは、ゲストスレッドID(すなわち、ローカルノードは、以下のAPIに内包される)およびタイムスタンプtだけである。ノードごとスレッドごとに異なる期間に記録された2以上の履歴が格納されてよい。いくつかの実施形態において、タイムスタンプtは、ゲストスレッド識別子に加えて用いられるAPIの一部である。
温かさと利用度との間の違いの一例は、以下の通りである。温かさは、スレッドの履歴を、履歴を含むノード上に現在あるページのセットに関連付けるが、利用度は、スレッドの履歴を、スレッドが動作しているノード上でのスレッドの現在のアクセスパターンに関連付ける。
以下は、利用度および温かさのための関数の例である。
(int)utilization(guest_thread_id)
(int)warmth(guest_thread_id)
一実施形態において、利用度は、以下のように追跡される。コード(本明細書では「バランサ」と呼ぶ)が、第2レベルページテーブルエントリを定期的に消去するが、メモリを解放することはない。例えば、実物理ページへの参照はページテーブル内でゼロアウトされるが、ページ自体は解放されない。次にページが要求された時、障害が発生する。しかしながら、参照は意図的または故意に除去されたので、ページアクセスが実際にはヒットであったであろうことがわかる(すなわち、参照が意図的にゼロアウトされたページでストールが起きた場合、そうでなければヒットがそのページに対して発生しただろうと判定される)。上記のサンプリングを実行することにより、参照は、利用度の近似を得るために、統計的にカウントされてよい。上述のように、そうでなければページに対するヒットが発生したのか否かを示すストールを引き起こすために、サンプリングが実行されてよい。引き起こされたストール中、ゲストスレッドおよびgpaのアイデンティティが、上述のように取得されてよい。
ページのセットに関する情報の管理
上述のように、ゲストスレッドは、ゲスト物理ページアドレスによって示されたゲスト物理ページと関連付けられている。いくつかの実施形態において、ゲスト物理ページは、それらのアドレスがポッドにわたって一意的であるという属性を有する。したがって、いくつかの実施形態において、消費および維持される管理データは、ゲスト物理アドレス(gpa)である。上述のように、ゲストスレッドは、(CR3およびFS−Base0などのレジスタを用いた一意的なゲストスレッド識別子である)ゲストスレッド番号によって示されるため、これらも、ポッドにわたって一意的である。
様々な目的(それらの例を後に詳述する)に対して、1セットのページを効率的に維持し、包括および排除について効率的にテストするデータ構造を有することが有用でありうる。利用できる時間および空間の両方において効率的なデータ構造の一例は、ブルームフィルタである(ここで、例えば、情報はビットマップにハッシュされる)。ブルームフィルタは、例えば、スレッドによるページアクセスの履歴をコンパクトに記録するために用いられてよく、ここで、スレッドアクセス履歴(ヒットであってもミスであっても)は、経時的に更新される。ブルームフィルタの長さが調整されてよい。
いくつかの実施形態において、このページセットは、経時的に更新される。実施形態の一例では、これを可能にする或るバージョンの基本的なブルームフィルタ(エージングブルームフィルタなど)が利用される。実施形態の一例では、2つのアクティブバッファを備えたエージングブルームフィルタが用いられ、これは、2つのブルームフィルタを維持することによってFIFO順序でデータをエージングし、ブルームフィルタの一方はフル稼働し、一方、他方のブルームフィルタは最新の履歴を保持する。
いくつかの実施形態において、1セットのページを維持するためにブルームフィルタまたはその他のデータ構造のどの特定のバージョンが用いられるのかに関わらず、必要とされる動作を記述する(および、ブルームフィルタに関して実行されてよい)以下のAPIの例が利用される。
//合計メモリサイズ(バイト)を取得する
size_t ts_bf_size(uint32_t num_bf,uint32_t num_hash,uint64_t num_bits);
//bfを初期化して破棄する
void ts_bf_init(struct ts_bf*bf,uint32_t num_bf,uint32_t num_hash,
uint64_t num_bits,uint64_t capacity);
void ts_bf_destroy(struct ts_bf*bf);
//bfをリセットする
void ts_bf_reset(struct ts_bf*bf);
//1つの要素を追加する
void ts_bf_add(struct ts_bf*bf,vm_paddr_t gpa,bool*aged);
//要素のセットメンバーシップをクエリする
bool ts_bf_contains(struct ts_bf*bf,vm_paddr_t gpa);
ページのアフィニティ
本明細書で用いるように、アフィニティは、現在動作しているノードに対するスレッドのアフィニティを示す尺度である。アフィニティは、上述のように、スレッドによるアクセスの履歴記録から決定されてよく、ここで、アクセスのセットの中で、特定のノードからのアクセスの回数が決定される。いくつかの実施形態において、比較的少数の最も最近アクセスされたページが追跡され、各かかるページについて、ページが最も最近そこから到着したノードid(識別子)(ページが移動した場合、または、そうでなければローカルノードID)が追跡される。ゲストスレッドについて、複数のかかるページが同じノードnに由来する場合、そのスレッドは、nに対する「アフィニティ」を有すると断言される(すなわち、スレッドが特定のノードからページを引き出している場合、そのスレッドは、ノードに対するアフィニティを有する)。例えば、スレッドによる最近の100アクセスが評価されると仮定する。例えば、それらの内の90%(または必要に応じて任意のその他の閾値)が別のノードに由来する場合、アフィニティ関数は、そのノードの識別子を返す。そうでなければ、関数は、ローカルノードの識別子を返す。
いくつかの実施形態において、上述の閾値の例(100アクセスで、アクセスの90%が特定のノードに由来する)は、(例えば、実験を通して)調節できる初期化パラメータである。トレードオフが存在しうる。トレードオフの一例は、この期間に保持されるページが多くなるほど、ノードに対するページのセットのアフィニティの程度が取得される前に、より多くのフラグメンテーションがシステム内で観察されうるというものである。例えば、所与のスレッドについて、1000のページがノード0上にあり、スレッドがノード1上にある場合、ノード0に対するアフィニティがあると決定するために、1000ページの待機がなされうるが、ページがノード1に移動した後に、残念ながら、スレッドがノード1からノード0へマイグレートすることがある。
以下は、アフィニティ関数コールの一例であり、ゲストスレッドIDを入力として、ノードidを返す。
node_id=affinity(guest_thread_id);
デューティ
vcpuは、ストールすることなしにかなりの数のゲスト命令を実行する場合、生産的であると判定されうる。
vcpuがマイグレートした後、そのvcpuは、生産的になる常駐ページを或る最少セットだけ有する必要がありうる。例えば、vcpuマイグレーション後に、通常は、vcpuが生産的になることができる前に必要とする〜15−30のページが存在することが観察されうる(これは、例えば、経験的に観察されうる)。いくつかの実施形態において、vcpuは、少なくとも閾値数のページアクセスを実行するまでノードにとどまるデューティを有する。(設定可能な)閾値は、スレッド用のワーキングセットの構築を開始するための初期メカニズムとして用いられる。本明細書の例において用いられるように、これらのページは、アクティブセットと呼ばれる。スレッドが計算を進めるために必要とするアクティブセット内のページの例は、スタックの最上部のページ、次を実行するためにスレッドが必要とするコードを有するページ、などを含む。この閾値は、例えば、スレッドがページにアクセスした後に別のノードにマイグレートするのを防ぐために設定される。vcpuがあまりに頻繁にマイグレートする場合、十分なゲスト進捗をなすために必要なゲストページのセットを利用する機会がない場合があり、したがって、非生産的でありうるため、実際には進捗がないことがある。
本明細書の例で用いられるように、グルーミングされたセットとは、或る期間にわたってゲストスレッドによって頻繁にアクセスされたページのセットのことであり、いくつかの実施形態において、その期間の持続時間が調整可能である。複数のグルーミングされたセットが、所与のゲストスレッドについて見られる場合がある。本明細書で用いるように、デューティという用語は、グルーミングされた(ワーキング)セットの形成の助けになるように、ゲストスレッドを或る期間中にノードにとどまらせる戦略要素を示すために用いられる。しかしながら、デューティ単独では、それが生成したグルームされたセットを維持するのに十分でない場合がある。
いくつかの実施形態において、デューティ関数コールは、ゲストスレッド識別子を入力として、デューティを示すブール値を出力として返す。例えば、ブール値は、ゲストスレッドがノードでそのデューティを完了したか否かを示すために用いられてよい。デューティが利用されうる一方法は、要求側の決定およびコスト項においてである。例えば、vcpuが、(例えば、非ローカルページアクセスに対するストールイベントに応答して)メモリのページの要求を送信するのかまたはマイグレートするのかを決定する時に、ゲストスレッドがノードでそのデューティをまだ完了していない場合、これは、vcpu(ひいてはゲストスレッド)をマイグレートするコストを高めることに寄与する。
(bool)duty(guest_thread_id)
デューティ状態は、スレッドがノードに到着して以来実行したアクセスの回数を計算またはカウントし、アクセス回数を閾値と比較することによって決定されてよい。閾値を満たすかまたは超えた場合、デューティは、完了しているかまたは他の方法で満たされている。閾値が満たされていない場合、デューティは完了していない。
メモリ圧迫
いくつかの実施形態において、メモリのニーズを満たすのに十分な空間がノード上に常にあることが保証される。しかしながら、いくつのvcpuがノード上で動作しているか、および、どれだけのI/Oが起きているのかによっては、ページを他のノードに移動することによって、ページをすぐにメモリからエビクトする必要がある場合がある。ページのエビクトが十分に迅速に起こりえない場合、そのノードへのメモリ圧迫は、危機的な状態にあるとみなされる。一部の例において、これは、すぐに対応すべき緊急状態である。エビクトに関するさらなる詳細については、ハウスキーピングと関連して後述する。
//ノード上の危機的なメモリが、その容量を所与としてノード上にあまりに多くのページが存在するか否かを報告している:
(bool)memory_critical(node_id)
優良度メトリック(Goodness Metric)
本明細書に記載の仮想化システムの効率は、(例えば、上述のように、ワーキングセットおよびスレッドの関連性の決定に基づいて)ゲストスレッドとそれらが必要とするページのセットとを調整することによって改善されうる。効率を決定する方法の一例は、本明細書で「優良度」メトリックと呼ぶものを定義することによる方法である。優良度メトリックは、スレッドの関数であり、ノードで動作している時のスレッドの効率を示す(ここで、スレッドは、異なるノード上では異なる効率を有しうる)。本明細書に記載されるように、スレッドは、実行時にめったにストールしない場合に「優良」とされる。後に詳述するように、優良度を追跡する様々な方法が利用されてよい。次いで、優良度メトリックは、より良くストールに対処する方法を決定するために用いられてよい。例えば、スレッドのマイグレーション、および、スレッドによって用いられるページのワーキングセットに対してそれらが有しうる効果が考慮されてよい。別の例として、優良度メトリックは、ページエビクト、転送要求への応答、および、(例えば、後述の「リソースマイグレーションネゴシエーション」に記載するように)それが、それらのページを用いるノード上のスレッドにどのように影響しうるか、に関する決定を行う時に用いられてよい。
優良度メトリックの計算の例は、以下の通りである。通例、ゲストスレッドができるだけ少ないミスでゲスト内のランタイムを積み重ねるほど、そのゲストスレッドは、良好に実行する(すなわち、正味ゲストランタイムが高いほど、そして、ミスが少ないほど、良好である)。ハイパーカーネル内のサブシステムにわたって一様に利用できるメトリックの一例は、「正味ゲストスレッドランタイム/ミスカウント」であり、ここで、「正味」とは、いくつかの実施形態において、ハイパーカーネルに起因するあらゆるスレッドアイドル時間を取り除くことである。実施形態の一例において、この時間は、スレッドを実行するvcpuがゲストに返されるまで積算され、時間の積算はストール後に停止される。vcpuがゲストに返された時に、タイムスタンプが記録されてよく、次にストールした時に、新しいタイムスタンプが記録される。次いで、2つのタイムスタンプの間の差が、積算された正味ゲストスレッドタイムに追加されてよい。これは、スレッドに対してスレッドごとに実行される。分子または分母が大きくなりすぎた場合、比率が同じままになるように、それらの値を割ってよい(例えば、両方2で割る)。
いくつかの実施形態において、I/O待ちに費やされる正味スレッド時間が追跡される。ゲストスレッドがI/Oのためにストールされると、そのスレッドを実行するvcpuは、上述のように、イベントテーブル内に配置される。I/Oが完了すると、そのスレッドを実行するvcpuは、イベントテーブルから外されて、タイダルツリー内に配置され、ここで、最終的には実行される。スレッドは、ベアメタル上で動作しても、本明細書に記載のハイパーカーネル上で動作しても、I/Oを実行する。ベアメタル上でのI/O待ちは、ベアメタル上のゲストスレッドのランタイムの一部になりえ、いくつかの実施形態では、同じことがハイパーカーネルにおいて起こる。ハイパーカーネルにおいて、ゲストスレッドのランタイムの一部としてI/O待ちを組み込む方法の一例は、以下の通りである。スレッドがイベントテーブルに配置された時のタイムスタンプが記録される。I/Oが後に完了した時に、2つのタイムスタンプの差が取られ、ゲストスレッドランタイムに追加される。次いで、(vcpuにおいて動作する)スレッドは、タイダルツリー内に配置される。
後に詳述するように、優良度メトリックは、コスト関数(例えば、スレッドのマイグレートを考慮した時に、その優良度メトリックが高すぎる場合、スレッドをマイグレートしないという決定がなされうる)、ハウスキーピング(例えば、バランサに関して、メモリの危機的な状況のためにページがエンビクトされる時に、効率的ではないスレッドを有するページが選択されうる)、および、タイダルツリー(例えば、動作する準備をさせるためにスレッドを含むvcpuをキューアップしようと試み、すでにキューアップされて動作の準備ができたvcpuでノードがオーバーロード状態であるとわかった時に、必ずしも実行の準備をすべきスレッドではなく、最悪すなわち最も効率の低いスレッドが、ルート内に配置されるよう選択されうる)のためなど、本明細書に記載の仮想化システムの様々な部分で用いられてよい。
以下は、優良度メトリックの2つの実施例であり、いずれの例も、以下の2つの内の一方に対する正味ゲストスレッドランタイムの比を計算する。
1.ミスの数、および
2.正味ホストランタイム(ゲストを除く)
上記の例はいずれも、計算が容易であり、監視が安価である。1つの例外は、2つ目の例がI/Oの待ち時間を含みうるのに対して、1つ目の例は含まないことでありうる。いくつかの実施形態において、(I/Oを含む)ベアメタルとの比較がなされる場合に、同じI/O処理がどちらの場合にも実行される(両者ともI/O待ち時間を含むか、または、I/O待ち時間を除外する)。I/O待ち時間の組み込みに関する詳細の例については上述した。
例示の目的で、以下の例の形態の関数を用いる。
//スレッドtの優良度がtよりも大きい場合にはtrueを返し、そうでない場合にはfalseを返す。
boolean isGood(guest_thread t,threshold t)
いくつかの実施形態において、2つ目の例を用いる場合、正味ホストランタイムは、優良度メトリックの分母として用いられる。
ページ競合
本明細書の例に記載するように、ページ競合は、別個のノード上の2以上のゲストスレッドが同じ短期間に1または複数の同じページを必要とする時に起きる。ページ競合の1つの示唆は、同じページで頻繁にストールし続けるゲストスレッドがノード上に存在することである。これは、ページが別のスレッドによって常にプルされているからでありえ、別のスレッドは、2つのスレッドの間でpingをやり取りする。(高度に)競合されるページの一例は、システムコールが実行される度にアクセスされるページである。例えば、Linuxオペレーティングシステムにおいて、ゲストオペレーティングシステムは、タイマーを含むページを更新するためにシステムコールを頻繁に実行する。しかしながら、Linuxカーネルは、本明細書に記載の仮想環境内でクラスタにわたって分散的に動作しているので、すべてのスレッドがタイマーを備えたページを更新しようとしている場合、ページのスラッシングが起こりうる。これは、パフォーマンスに悪影響を及ぼしうる。
ページ競合の結果、共通で必要とされるページをノードの間で移動させるか、または、競合するゲストスレッドをそれらが必要とするページと同じ場所に位置させうる。後者は、これらの特定の競合するページでの再ストールを潜在的に低減しうるが、多くのゲストスレッド/vcpuを同じ場所に位置させる、または、それらのスレッドによって必要とされる異なるページセットのストールを大幅に増加させるなど、副作用を有しうる。多くのvcpuを同じ場所に配置すると、vcpuがマイグレートする先のノードに、効率的に動作するpcpuが十分にない場合、潜在的にシステムへストレスが掛かりうる。ページの競合は、競合するゲストスレッドが、何らかのまたは非常に小さい共通部分を持つ異なるノード上に、それらがアクセスする多数のページセットを有する場合、競合するゲストスレッドを同じ場所に配置することを正当化しえない。いくつかの実施形態において、ページ競合を解決する方法の決定は、かかる課題を考慮に入れる。
以下は、ページ競合の問題を検出するために呼び出されうる関数の一例である。以下に記載するように、関数またはアルゴリズムは、特定のページについて、どのゲストスレッドが、どれだけの頻度で、特定のページを必要としているのかを決定する。例えば、関数は、ページを必要とするゲストスレッドについて、スレッドが短期間(例えば、最近)にページにアクセスした(例えば、そのページでストールした)回数のカウントを算出する。カウントが(設定可能な)閾値(例えば、5回)を超えた場合、ページは、競合されているとしてフラグを立てられる(例えば、ページに対するバイナリまたはブールフラグが設定されてよい)。これは、カウンタが閾値にある時に、ゲストスレッドがノード上の特定のページに対して競合していることを示す。
//関数page_contentionは、ハッシュ関数データ構造を利用し、
//それは、ゲストスレッドが最近に所与の閾値よりも多く
//同じページを要求したか否かを特定する//
//関数page_contention_listは、同じページ(gpa)で競合する
//他のゲストスレッドを返す
(bool)page_contention(gpa,guest_thread_id)
list of guest thread ids=page_contention_list(gpa)
本明細書に記載のコスト項の中で、一部は、以下のようなページ競合に対して取るべき動作を決定するために用いられてよい。
優良度メトリック:上述の優良度メトリックは、解決の必要がある問題があるか否かを特定するために、ページ競合の検出時に用いられてよい。例えば、競合するゲストスレッドが良好に実行中である場合、ページ競合の検出は、任意の特別な処理を必要としない。ページ競合は、無視することができ、例えば、任意のストールを扱う汎用コスト関数(優良度メトリックのためのAPIの例が上述されている)を用いて、決定がなされ続ける。
スレッドの頻度:いくつかの実施形態において、1つのスレッドが残りのスレッドよりも頻繁に動作する(すなわち、より頻繁にページにアクセスする)場合、これは、シングルスレッドのアプリケーション、または、シングルスレッド、おそらくメインスレッド)を例外的に利用するアプリケーションが存在する可能性があることを示すものである。これを、本明細書では、ポピュラースレッドと呼ぶこととする。
いくつかの実施形態において、ポピュラースレッドは、移動がそのワーキングセットのメモリ配置と矛盾しない限りは、ページ競合に対処するためにマイグレートを強制されることがない。いくつかの実施形態において、ページ競合によるポピュラースレッドのマイグレートを強制しないことで、パフォーマンスが向上する。
以下の関数の例は、アクセスの頻度に基づいて、ゲストスレッドの頻度を示す値を返す。
//アクセスの頻度に基づくゲストスレッドの頻度
(int)guest_thread_frequency(guest_thread_id)
スレッドの間の共通関心(common interest)のサイズ:ページ競合は、1セットの協調するスレッドの中の複数のスレッドがアプリケーションにおいてメモリを共有する時に起こりうる。ページ競合は、いくつかのユーザ並列作業負荷において観察されうるものであり、アプリケーションプログラマが、より細かい粒度の並列アプリケーションを書き込んで、アプリケーションレベルでの並行性を扱うと、より多くのページ競合が起こりうる。例えば、ゲストアプリケーションが独自のマルチスレッディングを実行し、独自の共有メモリを有すると仮定する。かかるアプリケーションのゲストスレッドは、大量の共通関心を有する可能性がある(すなわち、スレッドがアクセスするページの重複)。これは、例えば、異なるアドレス空間で動作するために、限られた量の共通関心を有するUnixでの一連の処理とは対照的である。高性能データベースが、広い共有アドレス空間を用いて独自のマルチタスキングおよびマルチスレッディングを実行してもよい。アプリケーションのゲストスレッドは、メモリの共通ページに従事している場合があるので、分離されるべきではない。または、例えば、アプリケーションは、或るスレッドの結果が別のスレッドによって利用されうるように、そのゲストスレッドの間に作業を分散していた。共通関心を決定するための本明細書に記載の技術は、アプリケーションレベルおよび/またはオペレーティングシステムレベルで実行されてよい。
ゲストスレッドは、スレッドが多数の共有ページを共有する場合に、同じ場所になければ競合するスレッドと同じ場所に位置することによってパフォーマンス利益を享受しうる。しかしながら、ペアになったゲストスレッドの間の共通関心のサイズを評価することが十分ではない場合がある。以下のシナリオ例を仮定する:スレッドAが、スレッドBとの多くの共通関心を有し、スレッドBが、スレッドCとの多くの共通関心を有するが、スレッドAおよびCには共通関心がない。AおよびCが別個のノード上に配置される場合、スレッドBは、ノードの間で頻繁にマイグレートすることによって、または、多くの共通に必要とされているページを頻繁に移動させることによって、その共通関心をAおよびCと共有しなければならない。いずれにしても、パフォーマンスは、A、B、および、Cが(それらが実行に十分なpcpuを有すると仮定して)同じ場所に位置するソリューションと比較して低下する。以下は、(スレッドがすべて、同じノード上でローカルに動作している限りにおいて)(複数の)ゲストスレッド間での共通関心のサイズを推定するAPIの一例である。
//ゲストスレッドとセット内のすべての他のゲストスレッドとの共通関心の評価。
//このセットは、競合するゲストスレッド、頻繁なゲストスレッド、または、ローカルのゲストスレッドなど、多くの方法で与えられうる
(int)common_interest(guest_thread_id,set of guest threads)
本明細書に記載するように、共通関心は、ノード上のゲストスレッドの間で共有されたページのセットのサイズを示す尺度(ページアクセスのパターンの類似性を示しうる)である。一例において、共通関心のサイズは、以下のように決定される。ゲストスレッドおよび1セットのスレッドのためのワーキングセットが取得される。スレッドのワーキングセットの重複/共通部分が決定される。
例えば、第1スレッドT1および第2スレッドT2があるとする。各スレッドは、最近アクセスしたページのそれぞれのワーキングセットW1およびW2を有する。例えば、W1およびW2の両方に共通するページが1ページだけである場合、T1およびT2は、あまり共通関心を持たない。しかしながら、W1およびW2の共通部分が多数のページである場合、2つのスレッドは、大量の共通関心を有する。
スレッドのためのワーキングセットは、共通関心が計算されているスレッドによって最近のアクセスの履歴(ヒットおよびミス)を記録するために用いられるデータ構造(例えば、ブルームフィルタ)にアクセスすることによって決定されてよい。上述のように、ミスは、ストール中に(例えば、CR3およびFS−Base0レジスタを用いて)決定されうる。ヒットは、サンプリングを実行することによって決定されてよい。例えば、上述のように、ページテーブルのサンプリングを実行するコードが実行され、そのコードは、ページテーブルを無効化するが、メモリからページテーブルを削除しない。無効化されたページに対するヒットが削除されているが、まだノード上にあり、観察された場合、ページテーブルは再び有効化され、ヒットが記録される。したがって、ヒット数は、サンプリングを介して近似されうる。ヒットは、スレッドの(最近の)履歴に記録されてよい。物理プロセッサが、ヒットの起きた時を示すハードウェアを備える場合、この情報も、ヒットであるページアクセスを記録するために取得されてよい。決定されたヒットおよびミスは、スレッドの履歴内にページアクセスとして記録されてよい。
W1およびW2は、スレッドT1およびT2による最近のアクセスであり、それぞれのスレッドに対応するそれぞれのビットアレイを用いて表されてよい。所与のビットアレイについて、「1」の数および位置は、サイズおよびアクセスされたページの両方に比例する。ビットアレイは、「AND演算される」。例えば、AND演算の結果がすべてゼロである場合、2つのスレッド間に共通関心はない。AND演算後の「1」のカウントが決定され、2つのスレッド間の共通関心のサイズを示す。「1」のカウントすなわち数は、例えば、ハミング重みとして計算される。このハミング重みは、T1とT2との間の共通関心の推定値である。
したがって、この例に記載したように、スレッドの最近のアクセス履歴は、「AND演算」を実行することによって取得および比較される。ブルームフィルタが用いられる場合、フィルタを生成するために用いられるハッシュ関数は同じページがブルームフィルタ内の同じ位置にハッシュするように、一貫していることが好ましい。この一貫性は、gpaがハッシュされることで提供されてよく、gpaは、クラスタ内のすべてのノードにわたってグローバルに一意的である。次いで、ハミング重みが計算され、ここで、この値は、共通関心のレベルを示す。
(同じまたは異なるノード上に存在しうる)複数のゲストスレッドに対する所与のゲストスレッドの共通関心が計算されてよい。一実施形態において、共通関心のサイズは、ゲストスレッドのセット内の各スレッドに関して所与のゲストスレッドについて決定された個々の共通関心(上述のように計算されたもの)の合計として計算される。例えば、T2、T3、および、T4に関するT1の共通関心が計算される場合、T2に対するT1、T3に対するT1、および、T4に対するT1、のペアごとの共通関心が決定および合計されることで、T2、T3、および、T4を含むセットに対するT1の全共通関心が決定される。
他のスレッドのセットに対するゲストスレッドの全共通関心を推定または他の方法で決定する時に、特定の個々の共通関心サイズ値が、合計からフィルタリングまたは除外されてよい。例えば、2つのスレッド間の共通関心が閾値より低い(例えば、ハミング重みが小さい)場合、値はフィルタアウトされる。一例として、特定のゲストスレッドがノード上でローカルに動作する100の他のスレッドに関して評価されており、100のスレッドの各々について、共通関心が1であると仮定する。合計すると、共通関心は100であり、これは、要求側のゲストスレッドとノード上のその他のスレッドとの間の高い共通関心を示唆しうる。しかしながら、実際には、各スレッドとの共通関心は少量だけである。したがって、閾値より小さい個々の共通関心サイズが、共通関心の全体サイズを推定する時にフィルタアウトされてよい。
いくつかの実施形態において、共通関心は、例えば、競合ページに対してストールが発生した時に、オンデマンドで評価される。例えば、後に詳述するように、共通関心は、ペアワイズリソースマイグレーションで計算または利用されてよい。したがって、共通関心は、ストールイベント中に(例えば、ページ競合フラグが設定された時に)、必要に応じて計算されてよい。
いくつかの実施形態において、計算された2つのゲストスレッド間の共通関心のペアごとの各計算結果が、(例えば、二次元アレイに)格納される。いくつかの実施形態において、共通関心の計算結果は、タイムスタンプに関連付けられる。例えば、ストールごとにページ競合が存在する場合、共通関心は、どのストールの後にも変化することがなく、ストールが発生する度に共通関心を計算する必要はない。タイムスタンプは、最後の共通関心が計算された時を決定するために用いられてよく、ここで、共通関心は、十分な量または閾値量の時間が経過した場合に再計算される(すなわち、2つのスレッド間の共通関心は、最近計算された場合には、ストールごとに計算される必要はない)。
メモリ状態:ページ競合に対処するためのゲストスレッドの移動は、将来的に複数のページを移動させうる。したがって、グルームされたセットがそのスレッドに対して生成された場所を知ることが、この決定を行うのに有用でありうる。(例えば、上記の関連セクションにおけるAPIを参照)。
いくつかの実施形態において、ページ競合の問題は、例えば、それがパフォーマンス(優良度メトリックによって特徴付けられうる)を害する場合、特別なケースとして(すなわち、本明細書に記載のストール対処とは異なって)解決されるだけでよく、いくつかの実施形態においては、ページ競合問題を解決するために、メモリ状態および他のスレッドとの関係性がネゴシエートされる。一部の例において、ゲストスレッドを同じ場所に配置することによって、ローカリティの点からさらなる利益を得て、pcpuの利用可能性の点でシステムにストレスを掛けない場合には、そうすることを拒否する理由がない場合がある。
VIOP:ページ競合のサブケースの一例は、I/O動作中にゲストスレッドがviop(仮想入力/出力動作:virtual input/output operation)と競合している場合である。いくつかの実施形態において、物理デバイスを表すviopが移動できない場合、競合するゲストスレッドは、viopを含むノードに移動され、I/O活動が続く限りはそこにとどまる。別の実施形態では、viopと、異なるノード上のゲストスレッドとの間でページを行ったり来たりさせるよりもコスト効率がよくなりうるため、I/O動作はリモートされる。
//viopとページを共有するゲストスレッドとの間の競合がある場合、trueを返す
(bool)viop_contention(gpa,guest_thread_id,viop_thread);
上述の履歴情報、メトリック、コスト項などは、メタデータとして格納されてよい。かかる情報は、例えば、スレッドがマイグレートを必要とするvcpuで動作している場合には、ノード間で転送されてもよい。仮想環境内で管理下にあるゲストページの数は、多数でありうる。スレッドの数も多数でありうるが、通常は、ページの数よりもはるかに少ない。したがって、わずか且つしばしば不完全なデータが、ページのワーキングセットとスレッドを関連付けるメタデータを効果的に管理するために、処理されるかまたは他の方法で対処される。スレッドおよびページを関連付けるメタデータは、サイズが大きくなりすぎたり(現行の特徴が予測不能に変化しうるために)古くなりすぎたりするのを防止されてよく、ここで、メタデータは、スレッドがマイグレートしうることを考慮して実装され、関連メタデータもマイグレートされる(メタデータによって参照されるページも移動されてよい)。一実施形態では、エージングブルームフィルタが、コンパクトな表現で上述のメタデータの一部を実装するために利用される。
後に詳述するように、上述の(スレッドをページのセットに関連付ける)メタデータは、vcpuストールの対処についての決定を行うための(例えば、重み付き非線形多項式内の)因子として用いられてよい。いくつかの実施形態において、vcpuがストールした時に、それは、ゲストスレッドを実行している。上述のように、ゲストスレッドは、ゲストオペレーティングシステムの制御下で(かつ、ハイパーカーネルの制御下ではない)、vcpuからvcpuへ移動してもよい。ハイパーカーネルは、スレッドがどのvcpu上で動作していても、スレッドのアクセスのパターンについてのその決定を基礎としてよい。vcpuがストールした時の対処を決定するためにその他の因子が用いられてもよい。
いくつかの実施形態において、スレッドについての上述の記録された履歴および決定されたメトリック/因子は、スレッドごとに格納される。
図13Dは、ゲストスレッド(ゲストオペレーティングシステムで動作するスレッド)に関する情報を格納するために用いられるテーブルの実施形態の一例を示す。その他のタイプのデータ構造が、必要に応じて用いられてもよい。
この例において、テーブル1330は、ゲストオペレーティングシステムで動作しているゲストスレッドを含む。各ゲストスレッドに続くのは、スレッド情報である。この例において、各行(例えば、行1332)は、例えば、その一意的な対応するFS−Base0レジスタ値によって識別される異なるスレッドに対応する。各スレッドについて、上述のスレッドごとのメタデータ情報への参照が記録される。この例では、各スレッドについて、温かさ(1334)、利用度(1336)、および、共通関心(1338)が、テーブルに記録される。(ブルームフィルタなどのデータ構造を用いて表された)スレッドよるページアクセスの記録された履歴が、テーブルに含まれてもよい。その他のコスト項/メトリックが、テーブルに格納されてもよい。所与の行(スレッド)のセルは、別個の情報へのリンクまたは参照またはポインタを含んでもよい。次いで、テーブル(例えば、ハッシュテーブル)は、スレッドごとの情報を取得するために、スレッドでインデックス化されてよい。したがって、上述のように、ゲストスレッドおよび/またはゲスト物理アドレス空間を識別することにより、図13Dの例に示したようなテーブルが管理されてよい。したがって、特定のスレッドが、(vcpuのアイデンティティを担うpcpuで動作する)vcpuに関連する情報でタグ付けされてよい。いくつかの実施形態において、スレッドメタデータのテーブルは、RAM(ランダムアクセスメモリ)に格納される。
いくつかの実施形態において、コンピュータシステム内の各ノードは、スレッドおよびスレッド情報のテーブルを有する。これは、特定のノードで実行しているすべてのスレッドのテーブルを効果的に形成する。スレッドに関する情報は、ノード間で転送されてもよい。
図13Eは、ワーキングセットおよびスレッドを関連付けるための処理の一実施形態を示すフローチャートである。いくつかの実施形態において、処理1350は、ハイパーカーネルによって実行される。処理は、ストールイベントの示唆が受信された時に、工程1352において始まる。いくつかの実施形態において、ストールイベントは、上述のように、非ローカルページ要求に関連する。別の実施形態において、ストールイベントは、上述のように、スレッドコンテキスト切り替えの検出に応じてトリガされる。
工程1354では、ストールイベントに関連する仮想プロセッサの状態が保存される。これは、上述のように、内部レジスタ、プログラムカウンタなど、プロセッサ状態のブロックの保存を含む。
工程1356では、参照されたゲスト物理アドレス空間およびゲストスレッド識別子の少なくともいずれか一方が、少なくとも部分的に、保存されたプロセッサ状態を評価することによって決定される。実施形態の一例において、プロセッサ状態の保存されたブロック内のCR3レジスタの値が取得される。CR3レジスタ値は、仮想プロセッサで実行しているプロセス(ゲストスレッド)によって参照されたゲスト物理アドレス空間に対応する。いくつかの実施形態において、仮想プロセッサで実行するゲストスレッドの識別子は、プロセッサ状態の保存されたブロックのFS−Base0レジスタ内の値(異なるゲストスレッドはFS−Base0レジスタ値を有するので、この値は、ゲストスレッドを一意的に識別する)にアクセスすることによって取得される。
工程1358では、履歴情報が、上述のように、工程1356における決定に少なくとも部分的に基づいて記録される。例えば、識別されたスレッドによってアクセスされた識別されたページが、スレッドによるページアクセスの履歴に記録されてよい。一例として、スレッドによるページアクセスの履歴は、ブルームフィルタなどのデータ構造を用いて格納される。様々なメトリックおよび因子が、記録された履歴に基づいて決定され、格納される(例えば、温かさ、利用度、共通関心、優良度、など)。
したがって、ページpを所与として、上述の技術を用いると、どのスレッドがpに対する強い必要性を有するのかが決定されうる。さらに、スレッドtを所与として、どのページがtによって強く必要とされるのかが決定されうる。次いで、後に詳述するように、様々な処理が、かかる情報に基づいて実行されてよい。
リソースマイグレーションネゴシエーション
上述のように、いくつかの実施形態において、非ローカルリソースが、(例えば、ゲストスレッドのために実行している)VCPUによって必要とされている時、それは、いくつかの既知の戦略(例えば、ページを所有するノードにリソースを要求するか、または、vcpuがオーナーノードにマイグレートすべきか)のコストを計算しようとする。それらのコストが計算されると、ハイパーカーネルコードは、コスト多項式に基づいて最低コストの戦略を選択する。
上述した例において、リクエスタ側での一連のコスト多項式が記載されており、ここで、要求されたリソースのオーナー側では、最低限の意思決定がなされうるか、または、意思決定が全くなされえない。ページが、移動不可能なデバイスによる現在の利用(例えば、移動できないハードドライブなどの物理デバイスによる直接メモリアクセス)によって、ノードに縛られている(wired)かまたはロックダウンされていることを除けば、ページは、通例、上記の例ではリクエスタに送信される。
一部の例において、要求されたページをオーナーが送信することが、最適ではない場合がある。例えば、リクエスタノード上のvcpuがページを要求すると仮定する。しかし、ページを積極的に利用してきたオーナーノード上のvcpuが30ある場合、要求されたページは、オーナー側で大量の利用があるので、要求されたページをリクエスタに送信することは最適ではない。その代わり、vcpuがリクエスタからオーナーへマイグレートするのと併せて、オーナーが要求を拒否または拒絶または否認することが最適である。
以下に記載の実施形態の例では、オーナーも、リクエスタから受信する要求にどう対処するのかを決定する方法を選択するために、一連のコスト多項式を有する(vcpuがマイグレートすると決定した場合、要求がないので、オーナー側で決定を行う必要はない)。オーナー側の一連の多項式を用いて、コスト効率がよいのは、要求を拒否することなのか、または、要求されたページを送信/マイグレートすることなのかを判定する(対して、リクエスタ側の多項式は、ページを要求するのか、または、ページを要求するvcpuをマイグレートするのかを決定するために用いられる)。リクエスタ側およびオーナー側の両方で決定することにより、要求を処理する方法に関して、より良好または改善された決定がなされうる。
いくつかの実施形態において、リクエスタおよびオーナーノードのコスト多項式は、互いに独立しており、他方がなくても存在しうる。
リクエスタおよびオーナーの決定多項式についての決定およびコスト項の例を以下に述べる。以下に記載の例は、ページの要求に言及しているが、本明細書に記載の技術は、適用できる場合、任意のその他のタイプのリソースに対応するよう様々に適合されてよい。
リクエスタ側の決定およびコスト項
リクエスタ側の決定
1.要求−−オーナーノードからリクエスタノードへリソースを送信することを要求する。
2.マイグレート−−ゲストスレッドを実行するVCPUをオーナーノードへ移動させる
リクエスタ側のコスト項
1.受信された拒否−−いくつかの実施形態において、この項は、拒否が受信されたばかりのページが要求されていることを示す。いくつかの実施形態において、拒否が受信されたばかりのページを要求することは、要求の極端に高いコストに寄与する。
2.スレッド効率−−いくつかの実施形態において、この項は、ゲストスレッドがいかに良好にこのノード上で実行してきたのかを規定する。いくつかの実施形態において、スレッド効率は、ミスの数と、(例えば、スレッドが実行中であり、ミスがない時の)スレッドランタイムとの比較に基づいて測定され、ここで、スレッドランタイムに比較してミスが少ないほど、スレッドの効率が高くなる。いくつかの実施形態では、ゲストスレッドがリクエスタノード上で良好に実行するほど、VCPU(およびVCPU上で実行中のゲストスレッド)のマイグレーションのコストが高くなる。スレッド効率の尺度の一例は、優良度メトリックである。
3.メモリ不足−−いくつかの実施形態において、この項は、要求側ノードがメモリ不足であるか否かを示す。いくつかの実施形態において、要求側ノードがメモリ不足であることは、リソースの要求にとって高コストになる。
オーナー側の決定およびコスト項
オーナー側の決定
1.送信−−要求側ノードにページを送信する
2.拒否−−新たな決定をすべきであることを要求側ノードに通知する
オーナー側のコスト項
1.縛られたページ−−いくつかの実施形態において、この項は、ページが、移動不可能なデバイスによって使用中であり、移動できないことを示す。いくつかの実施形態において、縛られたページは、リソースの送信にとって極端に高いコストになる。ページがマイグレート不可能なリソースまたはデバイスによって使用中であるか否かは、1セットのビットによって示されてよい。縛られたページのステータスは、一時的であり、時間と共に変化しうる(例えば、ページが直接メモリアクセスのためにハードドライブによってもはや利用されなくなった時)。
2.効率の比較−−いくつかの実施形態において、この項は、リクエスタ側の要求スレッドが、要求されたページを用いるオーナーノード上のどのスレッドよりもはるかに良好に実行しているか否かを示す。いくつかの実施形態において、リクエスタ側の要求スレッドが、要求されたページを用いるオーナーノード上のどのスレッドに比べても良好に実行するほど、要求を拒否するコストが高くなる。
3.ページの温かさ−−いくつかの実施形態において、この項は、要求されているページが、最近の要求によってオーナーノードに移動されたか否か、および、オーナーノード上で頻繁にアクセスされているか否かを示す。いくつかの実施形態において、値が高いと、「送信」のコストが高いことを示す。
いくつかの実施形態において、コスト多項式について、項の各々は、その項がどれだけ重要であるかを表すように重み付けされる。一例として、「受信された拒否」コスト項は、その他のコスト項が何であっても、ページにマイグレートするよりもページを要求する方が、はるかに高コストであることを反映するように重み付けされてよい(すなわち、要求コスト>マイグレートコスト)。同様に、「縛られたページ」コスト項は、拒否よりも送信の方が高コストであることを反映するように重み付けされてよい(送信コスト>拒否コスト)。いくつかの実施形態において、これは、提示される選択肢の中に他の選択肢が存在しえないことを反映する。そうでなければ、いくつかの実施形態において、重みは、パフォーマンスの解析および調整に基づいた値に設定されてもよい。
いくつかの実施形態において、短絡多項式評価が実行され、ここで、短絡制御メカニズムが、重みに加えてまたは重みの代わりに用いられる。重み付けおよび短絡の両メカニズムが用いられてよい。
ページを要求するためのトランザクションの例
以下は、ページを要求するためのトランザクションの一例であり、図14A〜図14Eに関連して説明する。
初期構成の例
以下の例では、以下のシナリオを仮定しており、これについては図14Aに関連して説明する。
図14Aは、ゲスト仮想マシンの初期構成の一例を示す。
・ポッド内に2つのノードがある(Node_1 (1402)およびNode_2 (1404))(ここで、ポッドの一例は、図1のコンピュータシステム100などの仮想化システムである)。
・VCPU_1(1406)が、Node_1上でGuest_Thread_1(1408)を実行している
・Page_1(1410)が、Node_2上にある
・VCPU_2(1412)が、Node_2上でGuest_Thread_2(1414)を実行している
・VCPU_3(1416)が、Node_2上でGuest_Thread_3(1418)を実行している
・この例では、その実行の一部として、Guest_Thread_1が、Page_1を必要とする。これは、要求を満たすために、ゲスト(オペレーティングシステム)から抜けて、ハイパーカーネルへ入らせる。この例において、上述のように、(Guest_Thread_1を実行している)VCPU_1は、1セットの関数(図14Bの工程1420)を呼び出して、ページを要求するのか、ページを現在有するノードにマイグレートするのかを決定する(例えば、上述したリクエスタ側コスト多項式を評価することによって)。いくつかの実施形態において、関数のセットは、共通のアプリケーションプログラミングインターフェース(API)を有する関数ポインタのアレイとして実装され、新しい値を取得するために重みを乗じた値を返す。値を得るために、関数によって返された値すべてが合計され、それらの個々の関数の各々について重みを乗じられる。こうして、最終的な多項式の結果値がマイグレーションコストについて得られ、一方で、別の多項式の結果値が要求コストについて得られる。最低コストの(すなわち、最も安価な)アプローチが取られる。マイグレーションコストおよび要求コストの計算に関するさらなる例を以下に記載する。
段階1の例
以下は、ページを要求するためのトランザクション例の第1段階の一例であり、これは、図14Bに関連して説明され、図14Aの例の続きである。
この例において、VCPU_1は、コスト多項式(上で列挙したものなど)に基づいて、ハイパーカーネルにおいてコスト分析(リクエスタ側)を実行する。この例では、工程1420に示すように、これは初期要求であるので、「受信された拒否」(RR)コスト項は0である。この時点まで、スレッド効率は非常に良好であり、そのため、「スレッド効率」値および重みの組みあわせは50であると仮定する。この例では、このノード上には利用可能な多くのメモリがあるので、「メモリ不足」(OOM)のチェックは0である。これは、「要求」決定に対して0のコスト、および、「マイグレート」決定に対して50のコストにつながる。したがって、この例において、結果は、(要求のコストがマイグレートのコストよりも低いので)Node_2からページを要求する結果となる。結果がマイグレートである場合、要求は行われない。
この例において、VCPU_1は、Page_1の要求パケットを作成し、様々な実施形態において、スレッド効率に関する情報、そのページがこのスレッドによって(短時間の)過去に要求された頻度、および、要求タイプ(例えば、読み出し/書き込み、など)を含む。この情報は、例えば、相互接続ネットワークを介して、Node_2に伝送される。後に詳述するように、要求と共に伝送された情報は、要求を拒否するかまたは要求されたページを送信するかを決定する時に、オーナーノード(Node_2)によって用いられてよい。要求と共に伝送された情報のその他の例は、上述のように、温かさ、利用度、および、共通関心など、Guest_Thread_1に対応するメタデータ情報を含む。スレッドについて記録された履歴も伝送されてよい。例えば、履歴のデータ構造(例えば、ブルームフィルタ)表現が、要求と共に伝送されてもよい。メタデータ情報の他の例と、リソースマイグレーションネゴシエーションにおけるそれらの利用については、後に詳述する。
この例においては、この時点で、VCPU_1は、Node_2からページまたはメッセージが到着するのを待つ。
段階2の例
以下は、ページを要求するためのトランザクション例の第2段階の一例であり、これは、図14Cに関連して説明され、図14Bの例の続きである。
この例において、Node_2は、Page_1を要求するパケットをNode_1から受信する。いくつかの実施形態において、ハイパーカーネルの通常動作の一部としてNode_2に格納された情報を用いて、Node_2は、例えば、上で列挙したオーナー側コスト項に基づいて、コスト分析(1422)を実行する。この例において、この分析の結果は、ページを送信するかまたは要求を拒否するかのいずれかを実行する決定である。
例示の目的で、この例では、要求されたページが移動不可能なデバイスに縛られておらず、Node_2上のスレッドGuest_Thread_2およびGuest_Thread_3によって最近頻繁に用いられていたと仮定する。
この例において、コスト項「縛られたページ」は、ページが移動不可能なデバイスによって積極的に利用されていないために、0を返す。この例では、重みがどうであっても、この項は0である。次に、この例において、効率についてのスレッドGuest_Thread_2およびGuest_Thread_3の分析の結果、かなりの効率になると仮定する。この例において、これら2つのスレッドは、リソースを得るために複数回のコールを行っており、Guest_Thread_1ほど効率的ではない。最後に、この例において、「ページの温かさ」コスト項が、このページについて計算される。この例において、このページは、Node_2上のスレッドGuest_Thread_2およびGuest_Thread_3のために最近何度もアクセスされていたので、これは、送信のコストを高くする。
2つの値の評価に基づいて、ページの送信について値「75」および要求の拒否について値「50」が決定される。この例では、それらの値に基づいて、要求が拒否される(要求を拒否するコストが、ページを送信するコストよりも低いため)。いくつかの実施形態では、拒否の理由が、拒否パケットの一部として含められ、拒否パケットは、この例においては、Node_1上で待機するVCPU_1に送り返される。
段階3の例
以下は、ページを要求するためのトランザクション例の第3段階の一例であり、これは、図14Dに関連して説明され、図14Cの例の続きである。
この例では、拒否パケットがNode_1に返され、VCPU_1は、Guest_Thread_1を実行できるように、実行準備される。いくつかの実施形態において、ゲストへのリエントリにより、Page_1上で再びストールが発生する。このストールは、ゲストから抜けてハイパーカーネルへ入ることを引き起こし、いくつかの実施形態においては、Page_1アクセスの解決についての対処を決定するために、コスト分析が再び実行される。この事例において、「受信された拒否」コスト項は、正の値を返し、その項の重みを伴って、要求およびマイグレートの決定のための値は、段階1とは異なる結果に終わり、ここで、段階3では、VCPU_1をNode_2へマイグレートさせる決定がなされる(マイグレートのコストが、今ではリソースを要求する新たなコストより低いため)。
リクエスタ/オーナーネゴシエーションの上記の3段階の例で見られるように、この例のネゴシエーションの最終結果は、図14Dの例に続く図14Eの例に示すように、Page_1の要求を満たすために、(Guest_Thread_1を実行中の)VCPU_1をNode_1からNode_2へ移動させることである。
様々な実施形態において、リクエスタ決定(要求、マイグレート)を支援するための様々なコスト項、および、オーナー決定(送信、拒否)を支援するためのコスト項を追加できる。オーナー決定を支援するために用いられるコスト項のさらなる例については後に詳述する。
図14Fは、リソースマイグレーショングレーションネゴシエーションのための処理の一実施形態を示すフローチャートである。いくつかの実施形態において、処理1430は、ハイパーカーネル(例えば、ページの要求を受信したターゲットノード上のハイパーカーネルであり、ここで、ターゲットノードは、要求されたページを所有する)によって実行される。この例において、ターゲットノードと、要求の送信元であるリモートノードとの間のペアワイズリソースマイグレーションネゴシエーションが実行される。処理は、リソース(例えば、物理メモリのページなど、物理メモリの必要な部分)の要求が受信された時に、工程1432で始まる。
例えば、要求は、第1ノード(要求の送信元である「リクエスタノード」または「発信元ノード」とも呼ばれる)上のpcpuで動作するvcpuによってなされる。要求を行うvcpuは、メモリの要求されたページを必要とするゲストスレッドを実行している。例えば、ゲストスレッドを実行している時、仮想プロセッサは、ゲストスレッドによって必要とされるページにアクセスできなかった(例えば、ページが発信元ノードでローカルに利用可能ではないため)。ストールイベントが発生した。ここで、ゲストスレッドは、物理メモリの必要とされるページにアクセスすることができない限りは、その処理を継続することができない。上述のように、発信元ノード上のvcpuは、1セットのコスト関数(例えば、多項式)を評価して、適切な戦略(メモリの必要なページに近づくために自身を発信元ノードにマイグレートするか、または、メモリの必要なページの要求を送信するか)を決定する。この例において、vcpuは、メモリの必要なページを要求する方が低コストであると決定した。したがって、発信元ノード上のゲストスレッドが非ローカルのページ要求でストールしたことに応答して、要求が、発信元ノードによって送信され、(要求されたページを所有する)ターゲットノード1402によって受信される。
受信された要求は、メタデータ情報も含み、その情報の少なくとも一部は、要求されたページを送信するかまたは要求を拒否するかを決定するために、ターゲットノードによって用いられる。要求は、要求されているリソースの識別子(例えば、要求されている物理メモリのページのgpa)を含む。要求に含まれるメタデータ情報は、メモリの要求されたページを必要とするゲストスレッドに対応するスレッドごとのメタデータを含む。メタデータ情報は、相互接続ネットワークを介してオーナーノードに伝送される要求パケットに含まれてよい。
例えば、図14Bの段階1の例に関連して説明したように、要求は、スレッド効率に関する情報、要求されたページがリクエスタノード上のゲストスレッドによって短期間の過去に要求された頻度、および、要求タイプ(例えば、読み出し、書き込みなど)を含んでよい。
リクエスタノードからの要求に含まれるスレッドメタデータ情報のその他の例は、温かさ、利用度、優良度/スレッド効率、アフィニティ、デューティ、(例えば、フラグによって示される)ページ競合、共通関心のサイズなど、上述したようなメタデータ情報を含む。要求を行うリクエスタ側のvcpuにおけるゲストスレッドのアクセスの(最近の)履歴も、要求に含まれてよい。上述のように、アクセスの最近の履歴は、ビットのアレイを用いてかかる情報を表すブルームフィルタに格納されてよい。送信されたアクセス履歴は、特定の最近の期間または時間窓内のアクセス、もしくは、例えば、メモリのページを必要とするリクエスタ側のゲストスレッドによってなされた最も最近のアクセスのセット(例えば、最新の10,000アクセス、または、任意の適切な数の最も最近のアクセス)を含んでよい。
工程1434では、受信された要求に含まれる情報に少なくとも部分的に基づいて、メモリの要求された部分を送信するかまたは要求を拒否するかの決定がなされる。決定は、1セットのコスト関数/多項式を評価することによってなされてよい。
コスト関数/多項式のセットは、リクエスタノードからの要求に含まれる情報、および、ハイパーカーネルの通常動作の一部としてオーナーノードに格納された情報を考慮してよい。例えば、オーナーノードでのコスト分析は、上で列挙したオーナー側コスト項に基づいてよい(例えば、縛られたページ、効率の比較、ページの温かさ、など)。オーナー側コスト項の別の例は、リクエスタノードから以前に受信した要求の数である。
戦略(すなわち、ページを送信するかまたは要求を拒否するか)のコストを評価する/決定する時、リクエスタノードからの要求内のスレッドメタデータ情報の一部は、オーナーノードに格納された情報と直接的に比較/ネゴシエートされうるが、リクエスタノードからのその他のメタデータ情報は直接的にネゴシエートされない。
直接的にネゴシエートされうる要求に含まれる情報の例は、明確に比較できる直接的な対応物/等価なメトリックをオーナーノード上に有する情報を含む。様々な実施形態において、かかる直接的にネゴシエートできる情報は、温かさ、利用度、および、共通関心のサイズを含む。
例えば、リクエスタ側からの要求に含まれるスレッドごとの情報は、オーナー側によってアクセス可能な/格納されたローカルノードレベルの情報と比較されてよい。オーナー側の情報は、(要求されたページを含む)オーナー側によって現在所有されているページに関する情報を含みうる。
一例として、要求に含まれるスレッドごとの温かさ情報は、要求されたページが(現在リクエスタ側にある)ゲストスレッドによってどれだけ最近にアクセスされたのかを示しうる。オーナー側の温かさ情報は、要求されたページが、オーナー側ノードでローカルに動作または実行しているスレッドによってどれだけ最近にアクセスされたのかを示しうる。
別の例として、オーナー側の利用情報は、或る期間にわたって、要求されたページにアクセスしたオーナー側で動作するスレッドの数、および、その頻度(例えば、最近の10秒間に、1スレッドが、要求されたページに一度アクセスした、など)を示す情報を含む。この情報は、ページが(任意のスレッドによって)そのノード上で非常に利用されているか否かを判定するために用いられてよい。オーナー側で、要求されたページの利用度が高い場合、ワーキングセットの中断につながることから、そのページを引き渡すべきではない(ここで、ノード上のすべてのスレッドが、それらの求めるページと同じ場所にあることを保証するために時間および労力が以前に費やされている)。したがって、オーナー側で構築されたこのワーキングセットを中断するコストは、高いはずである(そして、要求されたページは容易に手放すべきではない)。
利用度に関して、オーナー側は、リクエスタ側で実行中のゲストスレッドに対応する利用情報も有してよい。例えば、ゲストスレッドは、以前にオーナー側で実行されている場合があり、スレッドの動作についての履歴情報もオーナーノードに存在しうる。かかる利用情報がターゲットオーナーノードで利用可能である場合、その情報は、要求内の利用情報と比較されてよい。オーナー側利用情報が利用できない場合、かかる比較はなされる必要がない(すなわち、オーナーノード上にゲストスレッドの履歴がないので、ネゴシエートする関連情報がない)。どの情報がオーナー側にありうるかの保証がなくても、温かさ/利用情報が比較/ネゴシエーションのためにオーナー側で利用可能である/格納されている場合には、要求は、かかる情報を含みうる。
オーナー側コスト分析で利用されうるが直接ネゴシエートされないリクエスタ側からの要求に含まれる情報の例は、発信元/リクエスタノードに関して要求側vcpuにおけるゲストスレッドについて計算された情報を含むが、それに対しては、ターゲット/オーナーノードの対応物はない。様々な実施形態において、直接的にネゴシエートできないかかる情報は、優良度、アフィニティ、デューティ、ページ競合、および、記録された履歴を含む。例えば、ゲストスレッドがノード上でそのデューティ(例えば、上述のように、リクエスタノードに到着して以来の閾値数のアクセス)を完了させたか否かを示すデューティに関して、ページを必要とするゲストスレッドは実際にはオーナーノード上にはないので、オーナーノードに関してゲストスレッドについてのデューティを決定することはできない。
別の例として、リクエスタ側のゲストスレッドは、オーナー側で実行していないが、要求に含まれるゲストスレッドの最近のアクセス履歴は、ゲストスレッドがオーナー側でローカルに実行されてきた場合のゲストスレッドの動作方法または実行方法を決定するために、オーナー側で用いられてよい。
ページ競合に関しては、要求が、送信されたページ競合フラグを含む場合、これは、要求されたページが、ページにアクセスしようとするリクエスタ側のゲストスレッドによって非常に必要とされていることを、オーナー側に示す。上述のように、ページ競合が存在する場合、優良度メトリック、スレッドの頻度、および、共通関心などのコスト項は、取るべき行動の決定を容易にするために用いられてよい。
例えば、2(またはそれ以上)のゲストスレッドが、同じページについてページ競合する場合がある。2つのスレッドが同じノード上に共存するのがよいか否かを判定するために、共通関心の計算が用いられてよい。例えば、(リクエスタ側の)競合するゲストスレッドがリクエスタ側で実行中のその他のゲストスレッドとの間に有する共通関心のサイズは、リクエスタ側のゲストスレッドがオーナー側でローカルに実行中であるゲストスレッドとの間に有する共通関心のサイズと比較されてよい。共通関心は、上述の技術を用いて(例えば、ハミング重みを合計および決定することによって)計算されてよい。
リクエスタ側のスレッドに対するゲストスレッドの共通関心のサイズが取得され(例えば、動的に計算されるか、または、最近計算された共通関心が取得されてもよい)、要求に含められてよい。
ゲストスレッドは、オーナー側で実行中ではないが、オーナー側のスレッドのセットに対する(リクエスタ側で実行中の)ゲストスレッドの共通関心は、ゲストスレッドのアクセスパターン履歴が要求に含まれる場合には決定されうる。上述のように、要求に含めてアクセスパターン履歴を送信することにより、オーナー側は、ゲストスレッドがオーナー側でローカルに実行されてきた場合のゲストスレッドの動作方法または実行方法を決定してよい。例えば、ゲストスレッドのアクセスのパターンは、ゲストアプリケーションによって規定され、ゲストスレッドがどのノード上で実行しているのか、とは関係がない。ゲストスレッドがオーナー側で実行してきた場合、同じパターンのアクセスがなされただろう(ゲストスレッドの位置によって異なりうるものは、どのアクセスがヒットまたはミスであるかということである)。
したがって、要求内のスレッドのアクセスパターン履歴を受信することにより、オーナー側でローカルに実行中のスレッドに対するゲストスレッドの共通関心が計算されうる。例えば、上述のように、オーナー側で、オーナー側でローカルに実行中の各ゲストスレッドに対する(ページの要求を行ったvcpu内の)ゲストスレッドの共通関心の個々の推定値が計算および合計(または他の方法で集計)される(ここで、共通関心の個々の推定値は、それらが閾値未満である場合、合計から除外またはフィルタリングされてよい)。
いくつかの実施形態において、共通関心の計算は、要求されたページに対するゲストスレッドによるページ競合の決定に応じてトリガされる。上述のように、いくつかの実施形態において、共通関心の計算は格納され、共通関心が最後に推定された時を示すタイムスタンプと関連付けられてよい。(リクエスタ側またはオーナー側のいずれかまたは両方での)ストールに適用可能な共通関心の値が、(例えば、閾値期間内に)最近計算された場合、共通関心の推定値(または推定値の一部)は、(その閾値期間内に変化した可能性が低いので)再計算される必要はなく、それらの最近の値が再利用される(したがって、再計算を避けて、利用される計算リソースの量を削減できる)。
(要求を行うvcpu内の)対象ゲストスレッドが(リクエスタ側のスレッドと比較して)オーナー側のスレッドとの間に大きい共通関心を有する場合、これは、要求を拒否するコストの低下(または送信するコストの上昇)に寄与しえ、ゲストスレッドをオーナー側にマイグレートさせることになる。
したがって、ゲストスレッドが要求されたページに対する高い要求を高頻度で有するか否かを判定することに加えて、ゲストスレッド間でのアクセスページの重複、および、(例えば、最近)オーナーノードで実行中のスレッドとのアクセスページの重複が、要求されたページを送信するかまたは要求を拒否するかの戦略決定を行う際に利用されてよい。
上述のように、ページ競合が存在する場合、オーナー側がどのような決定をすべきかを決定するために、優良度メトリック/スレッド効率が用いられてもよい。例えば、競合するゲストスレッドがリクエスタ側で良好に実行していない(例えば、ページ競合フラグが設定され、リクエスタノードで実行している時のゲストスレッドの優良度メトリック値が低い)場合、ページ要求が拒否され、スレッドをオーナーへマイグレートさせることが好ましい。
いくつかの実施形態において、直接的にネゴシエートできない情報は、タイブレークを実行するために用いられてよい。例えば、リクエスタ側およびオーナー側の対応物を有するメトリックの比較(例えば、リクエスタ側の情報およびオーナー側に格納された情報を用いた比較)を実行した後に、タイ(同点)であると決定された場合に、優良度、アフィニティなどがタイブレークを実行するために用いられてよい。例えば、スレッドが、高い効率/優良度、または、リクエスタノードへのアフィニティを有する場合、オーナーノードは、多項式を用いて、ページをリクエスタノードに送信するよう決定しうる。一方で、スレッドが、低いアフィニティまたはリクエスタノード上で低い優良度/効率を有する場合、オーナーノードは、要求を拒否するよう決定し、スレッドを実行するvcpuをオーナーノードにマイグレートさせうる。等価な対応物のない因子も、(タイブレーク中に用いられるだけでなく)多項式計算の一部として用いられてよい。
オーナー側コスト項のその他の例は、上述のように、要求されたページが縛られているか否か、効率の比較、および、ページの温かさを含む。例えば、要求されたページがオーナーノードに現在縛られている(例えば、DMAのためにディスクによってアクセスされている)場合、オーナー側で行われてきた処理を阻害することになるので、ページの送信は、非常に高コストになる。
いくつかの実施形態において、ページ送信のコストおよび要求拒否のコストが計算される。最も低いコストを持つ動作(ページ送信または要求拒否)が、実行される動作である。
工程1436では、決定に少なくとも部分的に基づいて、応答が提供される。例えば、要求されたページを送信する決定が、ターゲット/オーナーノードでなされた場合、ページは、発信元/リクエスタノードへ送信される。いくつかの実施形態において、適切なデータ構造およびマッピングが、物理メモリのページの新たな位置を示すように更新される。例えば、オーナーは、メモリのページがリクエスタに送信されたことを記録してよく、その結果、現時点では以前のそのページのオーナーがページの要求を受信した場合に、ページの現在のオーナーに要求をリダイレクトできる。
例えば、要求が拒否される(すなわち、要求コストがページの送信コストよりも低い)場合、拒否メッセージ(例えば、パケット)が、リクエスタ/発信元ノードへ送り返される。この例では、拒否に応答して、リクエスタノードのvcpuは、そのコスト関数のセットを再評価してよい(例えば、図14Dに関連して説明した段階3の例で述べたように)。再評価は、以前の要求の拒否、または、要求が拒否された理由など、新しい情報を考慮に入れてよい。ページのマイグレートおよび/または要求のための新たなコストが計算されてよく、リクエスタは、決定された新たなコストに基づいて動作を選ぶ。
例えば、リクエスタノードのvcpuが、再評価に基づいて、自身をターゲットノードにマイグレートするよう決定した場合、そのvcpuは、上述のようにマイグレートされる。vcpuは現在新しいノード上にあるので、マイグレートされたvcpuで実行中のゲストスレッドに関連するスレッド情報も更新される。例えば、ゲストスレッドは現在新しいノード上にあるので、スレッドごとのメタデータ情報(温かさおよび利用度など)が更新される。
別の例として、ディスクが、要求されたページへの直接メモリアクセスを実行していたために、オーナー側が要求を拒否したと仮定する。かかるDMAは、一時的な動作である傾向がある。この情報に基づいて、リクエスタ側のハイパーカーネルは、ページを再び要求するが要求を行うのに待機もすると決定してもよい(例えば、マイグレートするか要求するかの決定に加えて、リクエスタ多項式は、再び要求しようと待つか否かを計算するために用いられてもよい)。いくつかの実施形態において、オーナー側のハイパーカーネルは、送信するか要求を拒否するかを決定するのに加えて、要求を再び試みるようリクエスタに命令するなど、別の動作を決定してもよい。
したがって、上述のように、いくつかの実施形態において、ストール時に、ゲストスレッドは、リソースのオーナーに要求を送信する。いくつかの実施形態において、この要求は、ノード間でさらなるローカリティ情報(例えば、ゲストスレッドに関する上記のメタデータ情報の例)を通信するために利用できる比較的多量の未使用空間を有しうるメッセージである。ノードのペアの間でのこの情報交換は、上述のように、2つのノード間の或るローカリティネゴシエーションを実行するために用いられる。また、ペアごとのネゴシエーションは、グローバルに一貫した状態情報を維持する必要性に置き換わりうる。ペアごとのネゴシエーションを通して、すべてのゲストスレッドについて、十分によい状態に収束されうる。1−n(1ノード対多ノード)タイプのネゴシエーションが用いられてもよいが、より高価でありうる。かかるネゴシエーションに関する詳細については、「リソースマイグレーションネゴシエーション」のセクションで上述しており、そこでは、ネゴシエーション中に他のノードに送信された情報のタイプの例も記載されている。様々な共通コストメトリックが、比較のために特定されてよい。例えば、共通関心のサイズの推定値は、2つのノード間で単一のゲストスレッドについて比較されてよく、コストの値ではないが、その代わりに、ゲストスレッドが潜在的に他のゲストスレッドとより共通した関心を有するノードの識別子である答えを提供する。この情報は、上記の例で記載したように、ネゴシエーションの効率を改善するために有益でありうる。上述のように、様々な実施形態において、優良度メトリック、メモリ状態、および、デューティ情報が、ネゴシエーション実行時に送信される。かかる情報は、共通関心およびその他の状態情報でさらに拡張されてもよい。かかる情報は、上述のように、多くの利用可能な空間を有する要求メッセージに追加される(例えば、これらのさらなるネゴシエーションパラメータがなければ、要求メッセージがほとんど情報を保持していないと仮定する)。
ハイパーカーネル、イベントテーブル、および、タイダルツリーのさらなる詳細および実施形態
ハイパーカーネルスレッド
以下に記載の例は、FreeBSDスレッドについて様々な言及を行う。FreeBSDは、ハイパーカーネルが協働しうるホストオペレーティング環境の一例にすぎず(例えば、ここで、ハイパーカーネルは、FreeBSDのサービス(I/Oおよびスレッド管理のためのサービスなど)を利用して、FreeBSDと共に働く)、本明細書に記載のFreeBSDの機能の一部または全部が、別のホストオペレーティング環境と共に、または、FreeBSDを利用することなしに、再実装されてよい。例えば、ハイパーカーネルは、FreeBSDを全く利用しないように書かれてもよい。一例として、FreeBSDなどのホストオペレーティングシステムを用いる代わりに、マルチスレッディングマイクロカーネルが、任意の必要な機能を提供するために構築されうる。これは、ホストオペレーティングシステムへの依存を最小化する。オプションを最大化するために、FreeBSDとハイパーカーネルとの間の相互作用の回数が制限されてよい。例えば、FreeBSDは、スレッド管理サービスを提供し、それらのサービスの一態様は、スレッドスケジューリングである。FreeBSDスケジューラは、スレッドに基本的な抽象化を提供し、スレッドは、物理プロセッサに割り当てられてよい(すなわち、FreeBSDスケジューラは、実物理プロセッサ上にスレッドを割り当てるエンティティである)。通例、FreeBSDよりむしろ、ハイパーカーネルが割り当てを制御することが望ましい。ハイパーカーネルスケジューラとFreeBSDスケジューラとの間の相互作用は、減少されうる。ハイパーカーネルスケジューラに関するさらなる詳細については、後に記載する。
ホストは、ユーザモードまたはカーネルモードのいずれかで動作してよい。ハイパーカーネルによって実行される処理は、ホストのユーザモードまたはカーネルモードのいずれかにあってよい。例えば、ハイパーカーネル処理は、FreeBSDにおけるユーザモードとカーネルモードとの間のコンテキスト切り替えの回数を削減するために、カーネルモードで実行されてよい。これは、レジスタの保存および格納、セキュリティ手段の管理など、オーバーヘッドを削減する。例えば、イベントテーブルは、ハイパーカーネル内でカーネルモードで実行されてよい(すなわち、FreeBSDカーネルモードで実行する)。
全体にわたって記載した実施形態の例において、ゲストオペレーティングシステム(およびゲストオペレーティングシステム上で動作するゲストアプリケーション)は、実際には、ゲストオペレーティングシステムが、ハイパーカーネルによって提供されたvcpuを管理している時に、自身が物理プロセッサを管理していると考える。ゲストオペレーティングシステムは、ゲストスレッドも管理する(ここで、ゲストオペレーティングシステムは、自身のスレッドスケジューラを有する)。これらのゲストスレッドは、(ゲストオペレーティングシステムの視点からは、物理プロセッサである)vcpuにおいて実行する。ゲストスレッドが生成されると、それらは、名称(例えば、ビット列である識別子)を割り当てられる。上述のように、ゲストオペレーティングシステムは、特別なレジスタ(例えば、FS−Base0レジスタ)にゲストスレッドの名称を配置し、そのレジスタは、ハードウェアアーキテクチャによってハイパーカーネルから見えるようになっている。したがって、ゲストスレッドは、識別されうる(ここで、ゲストスレッドは、FreeBSDスレッドとは異なる空間にある)。ゲストスレッドは、ゲストスレッドを実行するvcpuのアイデンティティを物理プロセッサが担う場合に実行される。
各ハイパーカーネルインスタンスに維持されるハイパーカーネルスレッドのタイプの3つの例は、以下を含む:ハウスキーピングスレッド、I/Oスレッド、および、vcpuスレッド。いくつかの実施形態において、ハイパーカーネルスレッドの数は、初期化時に知られ、各ハイパーカーネルインスタンスは、それが開始時にその上で実行中であるノード上のすべてのスレッドを生成してよい。
実施形態の一例において、ハイパーカーネル初期化の時に、各ノードで実行する各ハイパーカーネルインスタンスは、ハイパーカーネル内の各vcpuおよび各viop(仮想入力/出力動作)を表すために、FreeBSDスレッドを作成する。結果として、この実施形態の例においては、各vcpuおよび各viopが各ノード上に一意的な対応するFreeBSDを有することになる。補助スレッドが、ハイパーカーネルインスタンスによって生成されてもよい。
vcpuスレッドは、vcpuを表すために用いられるFreeBSDスレッドであり、vcpuおよびそのデータ構造に関連するソフトウェアを実行する。上述のように、各vcpu(仮想化システムにとってグローバルであり、クラスタ内の任意のノード上に存在しうる)は、各ノード上の一意的な対応するFreeBSDスレッド(本明細書ではサロゲートvcpuスレッドと呼ぶ)を有する。例えば、クラスタに4つのノードがある場合、各vcpuは、4つのノードの各々に1つずつの4つのサロゲートvcpuを有する。vcpuスレッドは、エンプティまたはフルのいずれかであってよく(すなわち、それぞれ非アクティブまたはアクティブ)、ここで、vcpuに対して1つのvcpuスレッドのみが、同時に実行すなわちアクティブになり(vcpuに対するすべての他のサロゲートvcpuは、エンプティすなわち非アクティブである)、ゲストオペレーティングシステムの違反になる(ここで、1つのvcpuが2つの異なるpcpu上で実行すべきではない)ことから、2つのノードが同じvcpuに対するアクティブなvcpuスレッドを有することは決してない。vcpuは、同時に1つのノード上にしか存在しえず、ここで、ゲストオペレーティングシステムのためのvcpuを実行しているvcpuスレッドは1つだけであり、その他の非アクティブなvcpuスレッドは待機している。したがって、サロゲートvcpuスレッドは、vcpuのためのプロキシとして機能し、vcpuが実行している位置(ノード)の代わりに処理を行う(例えば、vcpuスレッドがノード上のvcpuを実行し、一方で、vcpu自体は任意のノード上で動作しうる)。クラスタのノード上のサロゲートスレッドを利用して、例えばvcpuマイグレーション中に、ロッキングおよび同期の必要性を排除する。
vcpuスレッドは、ゲストオペレーティングシステム内のvcpuを実行しているか、または、ゲストオペレーティングシステム内のvcpuを実行しておらず、いくつかの他の動作を実行しうるか、いずれかである。例えば、vcpuスレッドは、vcpuのアイデンティティを担うよう命令される或る時点まで、ハイパーカーネルコードを動作/実行してよい。例えば、Intelアーキテクチャにおいて、vcpuスレッドは、VMエンター命令を実行してよく、その時点で、それは、ゲストvcpu内で命令を実行している(そして、例えばVMイグジットが発生するまでは、ハイパーカーネルで命令を実行していない)。例えば、vcpuスレッドがゲストオペレーティングシステム内でvcpuを実行している間にページフォールトが発生したので、VMイグジットが発生しうる。ページフォールトは、VMイグジットを発生させる。次いで、vcpuスレッドは、ゲストオペレーティングシステムコードの実行を停止し、その代わりに、ハイパーカーネルコードの実行を開始する。次いで、vcpuスレッドは、vcpuについて、ハイパーカーネルコードを用いて、(例えば、上述のコスト関数/多項式を用いて)vcpuをマイグレートするかページの要求を送信するかを決定する。vcpuスレッドは、それに対応するvcpuのためにのみ決定を行い、その他のvcpuには行わない。
vcpuスレッドが(所与のノード上の)vcpuに関連する作業を実行する方法の一例は、以下の通りである。例えば、vcpuがターゲットノードにマイグレートされると仮定する。マイグレートすると、vcpuのプロセッサの状態が、(例えば、継続を作成する際に格納されるように)明示的にメモリに保存される。次いで、この保存されたメモリは、(例えば、かかるネットワーキングを扱うよう構成されたネットワークスレッドによって)ターゲットノードへメッセージとして送信される。次いで、ターゲットノード上のサロゲート/補助スレッドは、ウェイクアップするよう信号送信または通知され、ターゲットノード上のpcpuで実行される(FreeBSDは、pcpuにvcpuスレッドを割り当てるために呼び出されてよく、ここで、ホストオペレーティングシステムは、物理プロセッサ上にスレッドをスケジューリングするために用いられる)。vcpuスレッドは、現在pcpu上で実行中であり、(メッセージに含まれるプロセッサ状態を用いて)ストールしたvcpuの状態を自身に復元する。VMエンターが実行される。ターゲットノード上のpcpuが、今や、vcpuのアイデンティティを担っている。次いで、pcpuは、ゲストオペレーティングシステムに戻ってよく、vcpuスレッドは、(ハイパーカーネルコードの代わりに)ゲストコードを実行し続ける。ゲストオペレーティングシステムの視点からは、フォールトが観察されなかった(ハイパーカーネルは、フォールトを阻止し、vmイグジット/エンターを実行した)。その代わり、ゲストオペレーティングシステムは、ページへのアクセスを試み、次の命令で、すでにページにアクセスしていた(ここで、ゲストオペレーティングシステムは、ハイパーカーネルによって実行された根底にあるマイグレーションを認識していない)。上述のように、クラスタのノード上のサロゲートスレッドを利用して、vcpuマイグレーション中にロッキングおよび同期の必要性を排除し、ここで、vcpuに対して1つだけのvcpuスレッドが同時に実行しており(vcpuに対するすべての他のサロゲートvcpuスレッドは、エンプティである)、2つのノードが同じvcpuに対するアクティブなvcpuスレッドを有することは決してない(すなわち、vcpuは、同時に1つのノード上にのみ存在しうる)。
この例において、FreeBSDは、vcpuスレッドのスケジューリングを制御しない。その代わり、vcpuスレッドは、初期化時に、待機状態で開始する。vcpuスレッドは、ハイパーカーネルがvcpuにウェイクアップするように信号を送信した時に、実行を開始するよう信号送信されるだけである。例えば、後に詳述するように、ハイパーカーネルスケジューラおよびタイダルツリーは、vcpuスレッドをバインドすることでアクティブにする(例えば、vcpuが所与のノード上で実行を開始できるように、そのノード上のvcpuのためのvcpuスレッドをウェイクアップする)。かかるvcpuスレッド(これらは、データ構造である)を作成することは、比較的コストがかからず、待機中には、全く処理を実行しない(または計算リソースを使い尽くさない)。vcpuを実行しているvcpuスレッドは、vcpuの表現であり、ハイパーカーネルの視点からは、スケジュール可能なエンティティである(ここで、後に詳述するように、vcpuスレッドは、ハイパーカーネルの制御下でウェイクアップまたはスリープするよう信号送信されうる)。様々な時点で、vcpuスレッドは、ゲストスレッドを実行しているが、別の時点では、実行していない場合がある。例えば、vcpuがノード上で実行している時、対応するvcpuスレッドは、(ゲストスレッドを実行している)vcpuを実行している。vcpuスレッドが実行していない時(例えば、vcpuが、vcpuスレッドの存在するノード上で実行していない時)、vcpuスレッドは、待機中またはスリープ中であってよい。
vcpuが実行している(例えば、継続ではない)場合、それは、vcpuスレッドで実行している。計算の実行がvcpuスレッドでなされ、ここで、vcpuがゲストスレッドを実行している場合、それは、ゲストスレッドを実行しているvcpuスレッドである(ここで、ゲストスレッドは、ゲストオペレーティングシステムによって管理される)。
vcpuスレッドが実行している時、ゲストスレッドが物理プロセッサであると考えているものに対応するレジスタ状態は、実際にはpcpu上で実行している(ここで、pcpuは、1セットのプロセッサ状態を有するvcpuのアイデンティティを担っている)。vcpuスレッドが実行している時、仮想プロセッサ状態情報が利用されている。例えば、ゲストスレッドは、プログラムカウンタ、レジスタなどを持っている。ゲストスレッドがタイダルツリー内にスケジューリングされ、vcpu上で実行を開始する時、vcpuは、プログラムカウンタ、レジスタなどを継承する。vcpuが動作している時、それは、ゲストが物理プロセッサであると考えているもののビット対ビットの正確な表現であり、実際、vcpuは、物理プロセッサ上で動作している(すなわち、物理プロセッサは、vcpuのプロセッサ状態を取ることによってvcpuのアイデンティティを担う)。任意の時間に、vcpuが物理プロセッサ上で動作している時、それは、ゲストが物理プロセッサとして考えているものと正確に一致する。物理プロセッサが仮想プロセッサにバインドされると、仮想プロセッサに関連するすべてのレジスタは、ゲストオペレーティングシステムが物理プロセッサであると考えているものに関連する情報と同じである。オペレーティングシステムがベアメタル上で実行している場合、pcpuは、vcpuと同じ状態を有することになる。
vcpuがストールした時、一部の例では、vcpuは、ゲストオペレーティングシステム(OS)が物理プロセッサであると考えるもの(本明細書に記載の仮想化システム/マシン内では、実際には仮想プロセッサ(すなわち、vcpu)である)において実行するゲストスレッドを実行している。一部の例において、ゲストOS(例えば、Linux、ここで、その他のゲストオペレーティングシステムにも対応可能である)内のスケジューラは、ハイパーカーネルの視点から、任意に見えうる或る根拠に基づいてゲストスレッドおよびvcpuのマッピングを頻繁に変更しうる(すなわち、上述のようなスレッドコンテキスト切り替え)。ゲストスレッド/vcpuの関連性は、ストールが処理される間は変わらない(vcpuは、ストールされている間は動作しないため)。ゲストオペレーティングシステムが、物理プロセッサであると考えているものの間でゲストスレッドを多重化する場合、これは、ハイパーカーネルによって気付かれる。上述のように、ハイパーカーネルは、(例えば、上述のように、プロセッサ状態のFS−Base0レジスタによって示された)vcpuで実行中のスレッドのアイデンティティを追跡し、関連スレッド遷移イベントに気付く。これは、部分的には、ノード、メモリ、および、スレッドの間のバインディング/アフィニティがゲストスレッドの観点から起きるからであり、ここで、スレッドコンテキスト切り替えが、上述のように、繰り返して起こりうる。例えば、上述のように、ゲストオペレーティングシステムが、ゲストスレッドを、自身が別の物理プロセッサであると考えている(ただし、ハイパーカーネルの視点からは実際には仮想プロセッサである)ものへ切り替える場合に、レジスタ(例えば、FS−Base0レジスタ)が更新され、これは、ハイパーカーネルにとって可視である。スレッドコンテキスト切り替えの検出は、ストールイベントの発生を引き起こす。
イベントテーブル(ET)のさらなる詳細および実施形態
以下では、イベントテーブルのさらなる詳細および実施形態について記載しており、イベントテーブルは、スレッドを考慮するよう構成されてよい。イベントテーブル(本明細書では「ET」と呼ぶ)およびタイダルツリー(本明細書では「TT」と呼ぶ)は、緊密に連携して動作しうる。ET上の動作は、単純、安価、スレッドセーフ、かつ、包括的であるように設計される。本明細書で用いられているように、協働するETおよびTTは、「ハイパーカーネルスケジューラ」と呼ばれる。
本明細書に記載した例において、ETは、将来に起こると予測される非同期イベントを見込んだデータ構造である。ETは、待たれているイベントが発生した時に参照されうるデータ構造であり、ETは、イベント発生の結果として1セットの動作を実行するようにハイパーカーネルに指示する。
いくつかの実施形態において、イベントは、抽象データ型であり;イベントは、その型に限定されるが明確に定義された動作セットを有しうる。
多くのスレッドが、ETへのアクセスを望みうるので、ETへのアクセスおよび更新の前後の同期が実行される。例えば、ET内のイベントを待つスレッドは、vcpuで実行中のゲストスレッド、もしくは、I/O動作の完了またはリモートノードからの完了割り込みの受信を待つviopスレッドでありうる。
ハイパーカーネルスレッドは、スレッドがすでにET内で待っていない限りは、直接的または間接的に待つためにFreeBSDスケジューラを呼び出さない。これについての1つの理由は、ハイパーカーネルの適切な決定を行うために、ハイパーカーネルがそのリソースのスケジューリングを厳密に制御することである。これらは、FreeBSDスケジューリング戦略と衝突する場合も衝突しない場合もある。いずれの場合でも、目標は、ハイパーカーネル/FreeBSDスケジューラ相互作用を最小限に抑えて厳密に制御することである。
いくつかの実施形態において、ハイパーカーネルスケジューラおよびFreeBSDスケジューラは、非干渉的である。例えば、FreeBSDスケジューラの暗黙的な呼び出しが除去される(例えば、cond_wait)。下層のI/Oデバイスが、それらの動作を完了させるために或る程度の時間を必要としうるので、viopは、waitを呼び出してよい。この場合、vcpuが、イベントテーブル内に表されてよく、イベント発生時に、vcpuは、タイダルツリー(TT)へ移行する。いくつかの実施形態において、I/Oは、FreeBSDドメインで実行される。したがって、いくつかの実施形態において、(例えば、vcpuではなく)viopが、cond_waitを呼び出す。
ETと相互作用する他のスレッドも存在しうる(例えば、ネットワークサブシステム内のスレッド)。以下は、非同期的イベントの例のリストである。
・応答型ページの受信
・非応答型ページの受信
・I/O完了通知の受信
・リモート割り込み通知の受信
・リモートまたはローカルのI/O動作の受信
・リモートまたはローカルの命令エミュレーション要求の受信
この例では、どのイベントも、ステータスを有する。ステータスは、{予定(anticipated),ポスト済み(posted),完了(completed)}の内の1つでありうる。本明細書に記載のように、vcpuが待つことを望むイベントをETに入れる決定をしたが、イベントをトリガするために必要なすべての作業を行っていない場合に、イベントは、予定の状態となる。イベントをトリガする作業が完了すると、イベントの状態は、予定からポスト済みに変わる。イベントが発生すると、状態は、完了に変更される(そして、ETから除去される)。(いくつかの実施形態では、イベントが発生すると、イベントテーブルからすぐに除去されるので、完了状態は必要とされず、例示の目的で本明細書に記載されている)。ET内には、完了済みのイベントはないことが好ましい。ETからパージされると、イベントを待つ任意のスレッドは、イベントに対応する適切な動作を取る。
いくつかの実施形態では、ページが要求されたことを示すペンディングビットが用いられる。ペンディングビットは、ページがすでに要求されている(ただし、ページはまだ受信されていない)ことを示すページデータベース内のページに関するビットとして実装されてよい。ページが要求された場合、要求されたページに対応するイベントテーブル内にイベントが存在することに注意されたい。したがって、ペンディングビットおよびイベントは両方とも必要でない場合がある。いずれにしても、情報は、ノードが同じページを2回要求しないことを保証するために用いられてよい(これは、限りなくページを要求することを防ぎうる−例えば、ノードは、ページを送信した時に、そのページが要求側ノードによって受信されたか否かをわからないーペンディングビットがこれを保証するのに役立ちうる)。
一部の状況においては、ページが正式に要求される前に、ページ到着イベントが発生しうる(すなわち、要求の成立がまだ途中である)。この場合、到着によってトリガされたETの更新は、イベントがまだポストされていないが、予定状態でイベントテーブルにあるとする。したがって、いくつかの実施形態において、ページが到着した後、イベント状態は完了としてマークされ、実際の要求はなされない。この場合、ETの更新がポスト済みとしてマークするようになされると、更新はその代わりに、持っているイベントが発生したかのようにその状態を完了へとシミュレートし、通常通りにイベントがイベントテーブルから除去される。また、ページが求められることなしに到着した場合、または、ページを待っている複数のスレッドがあった場合、ET内でページを待っているすべてのスレッドが、実行準備される。
考慮すべき別の問題の別の例は、以下の通りである。本明細書に記載の仮想化システムにおける不変条件の一例は、同じページに対しては同じノード上に重複する要求が存在しないことである。これは、ハイパーカーネルによる動員されたリソースの検索が最終的に終了することを保証するために行われる。これは、未処理の要求の完了に対応する第2イベントを有することによって解決されうる。したがって、任意のスレッド(元々のスレッドまたは後続のスレッド)が同じページでストールした場合、最初の要求が満たされるまで、別の要求は発行されない。
したがって、本明細書に記載の仮想化システムにおいて、各ノード上のあらゆるvcpuおよびあらゆるviopは、関連するFreeBSDスレッドを有する。いくつかの実施形態において、ハイパーカーネルは、vcpuと1:1で対応するvcpuスレッドを扱う。vcpuは、例えばハイパーカーネル初期化時に生成された関連FreeBSDスレッド(上述のvcpuスレッド)を有する。viopも、FreeBSDスレッドを有する。vcpuまたはviopは、ハイパーカーネルスレッドidで識別されるか、または、例えば、FreeBSDスレッド番号で表されてよい。いくつかの実施形態において、2つは、ばらばらに維持され、ここで、ハイパーカーネルvcpuまたはviopをFreeBSDスレッドに対応付けるテーブルが別個に維持される。これは、ハイパーカーネルおよびFreeBSDの相互依存を制限することに関して上述した理由でなされてよい。いくつかの実施形態において、どちらのFreeBSDスレッドがETからのイベントの除去に責任を持っていても、待機中のハイパーカーネルスレッドを、例えば、それに対応するFreeBSDスレッドに信号送信することによって目覚めさせる。このようにすることは、いくつかの実施形態において、継続に関するさらなる考慮を行う必要がないことを意味することに注意されたい。いくつかの実施形態において、計算の状態は、FreeBSDスレッド番号(または、同等に、ハイパーカーネル定義のvcpuまたはviop番号)によって表される。その後、この例において、FreeBSDは、スレッドランタイム状態を保存および復元する責任を持つことになる。
いくつかの実施形態では、どのイベントも、イベントタイプ(この例については、上で列挙した)、イベントステータス、および、イベントが完了した時に信号送信される1セットのスレッド、を含む。また、上述のように、複数のスレッドが、同じイベントを待つ場合があり、その場合、イベントが発生した時、イベントを待つすべてのスレッドがウェイクアップされる。これは、以下に記載のAPI例の副作用でありえ、本明細書に記載のET実施の例の一部である。いくつかの実施形態では、すべてのイベントが、リソースID(例えば、ゲスト物理ページのgpa)にも関連付けられている。いくつかの実施形態において、イベントテーブル内の(対応するリソースIDによって識別された)各イベントについて、イベントテーブルは、イベントを待っている(グローバルに一意的なvcpu識別子によって識別された)vcpuのリストを含む。
いくつかの実施形態において、イベントテーブルのためのAPIはすべて、セーフAPIとして(すなわち、或るミューテックスの下で)実装されるので、コレクションは、ホーアスタイルモニタとみなされてよい。
//安全にイベントをイベントテーブルに挿入する
//my_eventが、イベントテーブルへのインデックスであってよい
//イベントがすでにイベントテーブル内にある場合、
//イベント「e」が発生した時に起こされるスレッドのリストにスレッド「t」を追加する
my_event=ts_insert_event(thread t,event e);
//指示されたイベントのステータスをポスト済みに変更する
ts_change_event_status_to_posted(my_event e);
//それを待つすべてのスレッドに開始するよう信号を送信し、イベントテーブルからeを除去する
ts_trigger_event(my_event e);
タイダルツリー(TT)およびスケジューリングのさらなる詳細および実施形態
以下では、タイダルツリー(TT)およびスケジューリングのさらなる詳細および実施形態について記載しており、これらは、いくつかの実施形態において、スレッドを考慮する。
最適化タイダルツリー
図15Aは、タイダルツリーの別の実施形態を示す。この例において、タイダルツリーの別の実施形態は、「最適化タイダルツリー」と呼ばれ、上述のタイダルツリーを最適化または平坦化または縮小したバージョンである。
タイダルツリーの上記の実施例において、タイダルツリーは、物理ツリー(例えば、(ハイパースレッドを含む場合)深さ5のツリー)として実装され、ここで、ツリーの各ノード/頂点は、実行準備のできたvcpuの作業キューを有していた。TTの物理ツリー実施例において、各第2レベルのサブツリーは、ノード上に存在し、ツリーにおける各頂点は、計算階層の物理部分を表していた。例えば、リーフは、ハイパースレッドに対応していた。1つ上のレベルは、ハイパースレッドを組み合わせてコアにすることを表していた。そこから1つ上のレベルは、それが含むすべてのコアを含む物理プロセッサを表していた。そこから1つ上のレベルは、それが含むすべてのプロセッサを含むマザーボードを表していた。最後に、1つ上のレベルは、タイダルポッドを表していた(すなわち、システム内のマザーボードすべて)。実行準備のできたvcpuをキューする時に、vcpuが最後に動作したpcpuのキューにvcpuを配置する試みがなされる。そのキューが満杯だった場合、vcpuを作業キューに追加できるまで、1つ上のレベルの次のキューが検索され続ける。
深さ5のTTの上記の実施例において、ルートの位置は、任意であってよいが、いくつかの実施形態においては、周知のノードまたは起動時に指定されたノード上であってよい。ルートは、どのノード上のpcpuキューにも入れられていない実行準備のできたタイダルポッド全体のvcpuのキューを含む。いくつかの実施形態において、ルートキューを含むノードは、エンキュールートおよびデキュールートのメッセージに応答するが、ルートの位置は、vcpuマイグレーションポリシーとは無関係であってよく、いくつかの実施形態では、キューを維持するノードであってよい。
タイダルツリー構造の最適化バージョンにおいて、(深さ5のTTなどで)物理ツリー構造を構築または実装する代わりに、最適化タイダルツリーは、ハードウェア構成内の各物理プロセッサに対応する1セットのキュー(例えば、図2の例におけるハイパースレッド)、および、グローバルにアクセス可能なキューとして実装され、ここで、ツリーの階層は、訪問順で置き換えられる。例えば、ハイパーカーネルに割り当てられた各pcpuに対して1つのキューが存在する。(例えば、後述の分割スケジューラについての議論を参照)。物理プロセッサの各々に対応するキュー(例えば、キュー1502および1504)は、本明細書では「pcpuキュー」と呼ばれ、グローバルにアクセス可能なキュー(1506)は、本明細書では「ルート」と呼ばれる。上記の深さ5のタイダルツリーの二次元構造ではなく、最適化タイダルツリーは、一次元構造を用いて実装される。この実装例において、pcpuキューは、深さ5のタイダルツリーのリーフの例であり、一方で、グローバルにアクセス可能なキューは、深さ5のタイダルツリーのルートキューの一例である。
最適化タイダルツリーは、深さ5のタイダルツリーの上記実施例と比較して、作業キューの数が削減されている。例えば、ハイパーカーネルに割り当てられたN個の物理プロセッサがある場合、最適化タイダルツリーにはN+1個のキュー(N個の物理プロセッサおよび1個のグローバルアクセス可能なルートキュー)があるが、深さ5のTTは、ツリー内の頂点の数に等しい数のノードを有する。したがって、最適化TTにおいてトラバース/訪問するためのキューの数が削減される。
したがって、上述のように、最適化TTのこの実施例において、最適化TTは、キューのセットとして実装され、ここで、ツリーウォークを模倣したトラバースアルゴリズムと共に、ハイパーカーネルに割り当てられた各物理プロセッサのための1つのキューが存在する。一実施形態において、pcpuキューは、実行準備のできたvcpuの先着順(FCFS)リストとして実装される。いくつかの実施形態において、pcpuキューが検索される順序は、キャッシュアフィニティを実現するために予め決定される。例えば、概念ツリーのキャッシュレベルに対応する検索パスが用いられる。キャッシュレベルの知識は、深さ5のTTの上記実施形態で述べたように、ツリーの頂点上に複数のキューを維持するのではなく、物理プロセッサのトラバースアルゴリズムに埋め込まれる。トラバースの順序は、起動時に固定されてよく、本明細書に記載の仮想化システムの物理トポロジに対応する。
例えば、ハイパーカーネルに割り当てられたノード上にp個の物理プロセッサがあると仮定する。各ノード上には、FreeBSDのために確保されたn個の物理プロセッサがあり、残りのp−n個の物理プロセッサは、vcpuのスケジューリングに用いるようにハイパーカーネルのために確保される。k個のノードを仮定すると、スケジューリングされるvcpuは、k*(p−n)個である。
上述のように、各pcpuは、実行準備のできたvcpuの関連FCFSリストを有する。
上述のように、vcpuは、ストールすると、ノードのイベントテーブルに配置されて、イベントの発生を待つ。この状態で、vcpuはマイグレートできない。イベントが(例えば、或るpcpu peによってトリガされて)ノード上で発生すると、peは、そのイベントを獲得して、このイベントを待つすべてのvcpuを仮想タイダルツリーにエンキューし、その後、以前に行っていたことは何でも継続する。(プロセッサpeは、確保されたFreeBSDプロセッサまたは確保されたハイパーカーネルプロセッサのいずれかであってよく、どちらのプロセッサがイベントを処理していても、それは、イベントを待つ適切なvcpuを解放し、それらをタイダルツリー上へキューすることが好ましい)。
pcpu pnewが利用可能になると、それは、例えば、動作させるのに最も適切なvcpuを検索することによって、自身に作業を割り当てる。次いで、pnewは、そのvcpuのアイデンティティを担い、vcpuは動作を開始する。
vcpuを(例えば、ETから外された後に)TT上へ配置(「エンキュー」)する処理、ならびに、(例えば、匿名のpcpuが実行すべき作業を探している時に)TTからpcpuへデキューする処理、に関するさらなる詳細および実施形態について、以下に詳述する。
TT上へのVCPUのエンキュー
上述のように、vcpuは、(例えば、vcpuが待っていたイベントが発生したために)イベントテーブルから除去された時、または、マイグレートするvcpuがノードに到着した結果として、キューされる。どちらの場合も、vcpuは、適切なpcpuキューを見つけられる場合には、このノード上の選択されたpcpuにキューアップされる(すなわち、特定のpcpuに対応するキューに配置される)。
pcpuキューが検索される順序は、キャッシュアフィニティを実現するために予め決定されてよく、ここで、いくつかの実施形態において、トラバース順序は、キャッシュ階層に従う。キャッシュ階層すなわちキャッシュの階層の一例では、同じコア上の2つのハイパースレッドがキャッシュデータを共有し、プロセッサチップ上の複数のコアがキャッシュデータを共有し、マザーボード上の複数のプロセッサがキャッシュデータを共有する。
いくつかの実施形態において、コア上の複数のハイパースレッドが、同じプロセッサハードウェアを利用していて、互いの実行と衝突する場合があるため、可能であれば、同じコア上の複数のハイパースレッドの過密スケジューリングが避けられる。したがって、かかる実行の衝突を防ぐために、ハイパースレッドを分散させることが望ましい場合もあるが、できるだけ多くキャッシュアフィニティを利用して、2つの潜在的に衝突する目標という結果になることが望ましい場合もある。したがって、いくつかの実施形態において、用いられるプロセッサの特定のタイプに対して、検索順序が、(例えば、起動時に)確立される。
一例として、vcpuの実行準備ができると、実行準備のできたvcpuを配置すなわちエンキューするキューの検索が、以下のように実行される。出発点として選択されたpcpuから開始する。一例として、検索は、vcpuが最後に動作したpcpuに対応するキューで開始される。いくつかの実施形態において、各vcpuの状態は、vcpuが動作した最後のノードおよびその最後のノード上のpcpuを記録するように拡張される。利用可能なpcpuキュー(ひいてはpcpu)の検索は、vcpuが動作した最後のpcpuで開始する(vcpuが最後に動作した時に、それが現在存在するのと同じノード上にあったと仮定する)。vcpuがマイグレートしたばかりである(したがって、以前に動作していたpcpu上で動作できない)場合、または、ちょうど始動している場合、アクセスまたは訪問する第1pcpuキューは、任意に選択されてよい。上述のように、1つの目標は、コアにオーバーロードさせないことである。いくつかの実施形態において、検索は、後に詳述するように、可能であればフルセットのコアにわたって実行準備のできたvcpuを分散させるようにバイアスされる。
一例として、検索は、選択されたpcpu(すなわち、上述のように、可能であれば、vcpuが最後に動作していた物理プロセッサ)から始まり、キュー長がゼロ(すなわち、キューがエンプティ)である同じコア上にはないキャッシュ関連pcpuが検索される。1つも見つからなかった場合、実行準備のできたvcpuをすでに有するコア上のvcpuをキューする試みがなされる。例えば、キュー長が1であるキュー、次に、2であるキュー、最大キュー長を有するキューまでが検索される。検索の順序は、キャッシュ階層に従う。一例において、第1すなわち出発pcpu(キュー)にvcpuをエンキューする試みが最初になされ、次にその兄弟、次に従兄弟、次に第2従兄弟、などへの試みが続く。一実施形態において、pcpu pの兄弟は、pと同じコアを共有するハイパースレッドのことである。従兄弟プロセッサとは、共通の先祖を有するpcpuのことである。従兄弟pcpuの一例は、同じチップの別のコア上にあるpcpuである。かかるpcpuが見つからない場合、チェックされる次のpcpuは、別のチップまたはソケット上にあるが同じマザーボード上にあるpcpuである(すなわち、pへの物理的接続を有するもの)。このように、暗黙的に、最も温かいキャッシュが見つけられ、vcpuは、このノード上の利用可能なpcpu上に分散される。
別の例として、vcpuの実行準備ができると、可能であれば、対応するキューがエンプティのスロットを有する(すなわち、キュー長が最大長未満である)場合に、vcpuが最後に動作していた物理プロセッサ(例えば、ハイパースレッド)から、検索が開始される。そうでなければ、検索は、ノード上ですべての可能性がなくなるまで、次のpcpuなどに進む。その後、vcpuは、ルート上に配置される。
様々なトラバース順序が、起動時に設定されてよい。一例として、コアの番号順のリスト内の次のコアが検索される。vcpuをそのコア上に配置できる場合、vcpuは、そのコア上に配置される。これは、vcpuが最後に動作していたpcpuと同じキャッシュラインの一部を共有する結果になりうる。上述のように、いくつかの実施形態において、同じコア上のハイパースレッドの利用が、そのコア上の兄弟ハイパースレッドがビジーである場合に回避される。
図15Bは、実行準備のできたvcpuをエンキューする先のpcpuキューの検索の一実施形態を示す図である。図の例において、ノードのためのマザーボードは、(例えば、マザーボード上の2つのソケットに)2つのチップを有しており、各チップは2つのコアを有し、各コアは2つのハイパースレッドを有する(その他のハードウェア構成も可能でありうる)。したがって、この例に示すように、PCPU0〜PCPU7としてこの例にラベル付けされた8つのpcpuが存在する。検索がPCPU0(1510)から始まると仮定する。vcpuをPCPU0上に配置できない場合、この例において、検索で訪問される次のpcpuキューは、PCPU2に対応するキューであり、PCPU2は、同じチップ上にあるが、PCPU0とは異なるコアである。この例において、PCPU2を次に訪問することにより、PCPU1がビジーである場合に、チップ0のコア0のオーバーロードを回避できる。さらに、これは、(例えば、他のコア上のpcpuに)ノード上のvcpuを分散することを試みる。
この例において、PCPU2が訪問された後の次のPCPUは、PCPU1である(例えば、PCPU1が以前にビジーであった場合に、検索のこの時点ではもはやビジーではない可能性があり、オーバーロードが回避されうる)。その後に訪問されるPCPUは、PCPU3であり、次はPCPU4(この例においてはマザーボード上の他のチップに移動する)、次はPCPU6、次はPCPU5、次はPCPU7である。
この例において、上記の順序を規定する反復式は、(+2−1+2)+1(+2−1+2)などである。「クリーネ」または正規表現パターンとして、上記は、以下の式の例によって規定される。
[(+2−1+2)+1]^*
最大キュー長以下の任意の適切なpcpuキューがノード上で見つからない場合、vcpuは、クラスタ内の任意のノード上で動作するために利用可能なvcpuのグローバルアクセス可能なFCFSリスト(図15Aに記載したようなルート)上にキューされる。vcpuは、例えば多項式戦略のローカリティに基づいた理由で、特定のノードにあるので、他のノード上のpcpuのためのキューは評価されない、すなわち、vcpuは、特定のノードへマイグレートされているか、または、それが存在するノードにページが移動されるように要求していた。
別の実施形態では、ルート上にvcpuを配置するのではなく、そのノードについて最もパフォーマンスの低いvcpuが、エビクトされ、ルートキュー上に移動される。次いで、キューされるvcpuは、最もパフォーマンスの低いvcpuがエビクトされたpcpuキューに配置される。
ノード上のpcpuをオーバーロードしないように注意することが好ましく;ハイパーカーネルスレッドを実行するFreeBSDスケジューラキューは、できるだけ短く維持されることが好ましい。いくつかの実施形態において、実行準備完了にされうる(すなわち、TTのpcpuキューおよびルートキューに配置されうる)タイダルツリースレッドの最大数は、ハイパーカーネル初期化パラメータとして指定される。
仮想化システム上の利用可能なpcpuと比べてvcpuが多すぎる場合、CPU負荷は、ポッドのノードの間でバランスを取られることがj好ましい。利用可能なpcpuと比べてvcpuが多すぎるという判定は、実行準備のできたタイダルツリー内のvcpuの総数を追跡することによってなされてよい。許容できる或る程度のレベルのオーバーコミットメントがあると仮定できる。このレベルは、起動時パラメータによって確立されてよい。オーバーコミットメントに関するさらなる詳細については後述する。ノードのタイダルツリー(例えば、ノードにローカルなpcpuに対応するpcpuキューのセット)が過密になると(すなわち、コミットメントレベルを超えると)、ハイパーカーネルは、例外動作を実行してよく、ここで、上述のように、タイダルツリーは、実行準備のできたvcpu(例えば、ノード上の最もパフォーマンスの低いvcpu)を選択し、それを特別なキュー(上述のように、グローバルTTルート)に配置し、ここで、ポッド全体に対して1つのルートが存在する。
ノードのpcpuキューからエビクトされ、グローバルアクセス可能なルートキュー上にバンプされるvcpuは、以下のように選択されてよい。エビクトされるvcpuは、ゲストスレッドを現在実行しており、したがって、関連する優良度メトリックを有する。このゲストスレッドをエビクトすることにより(ゲストスレッドを実行しているvcpuをエビクトすることにより)、これは、ゲストスレッドの必要とするメモリの位置、および、そのゲストスレッドと共通関心を有しうる他のゲストスレッドのメモリの位置に影響しうる。いくつかの実施形態において、(将来プルされるルートにvcpuを配置することによって)どのvcpuをエビクトするのかを決定するために、優良度メトリック、メモリ状態、および、共通関心(これらの例については上述した)など.1セットの項が考慮される。例えば、(例えば、優良度メトリックを用いて測定された)最もパフォーマンスの低い(ノード上のpcpuキュー内の)vcpuがエビクトされ、グローバルアクセス可能なルートキュー上に配置される。
pcpuをビジーに維持することとキャッシュラインを再利用することの両方が重要でありうるが、いくつかの実施形態において、本明細書に記載のトラバースアルゴリズムは、キャッシュラインの再利用よりもpcpuをビジーに維持することに向かうバイアスをアサートするが、あまりに多いハイパースレッドでコアをオーバーロードする犠牲を払うことはない。
本明細書に記載のスケジューリングアルゴリズムは、スレッドアイデンティティを考慮してよい。例えば、本明細書に記載のスケジューリングアルゴリズムを用いて、vcpuが実行した最後のpcpu上にvcpuを復元する試みがなされる。vcpuはゲストスレッドを実行していた。そして、ゲストスレッドは、vcpuがストールしていた間に変化していない。vcpuが復元される時、識別されうる最も有利なpcpuに復元されるだけでなく、vcpuの復元時に、スレッドも、スレッドが実行していた最後のpcpu上に同時に復元される。これは、(L1、L2、または、L3キャッシュを観察することは可能ではない場合があるので)発見的であるが、このアプローチが最適であり、ここで、スレッドは、それが実行した最後のpcpu上、または、識別されうる同じコア上にはない最も近い関連物の上に配置される。
いくつかの実施形態において、コアは、オーバーロードを防止される。例えば、上述の検索は、フルセットのコアにわたってvcpuを分散させるようにバイアスされてよい。バイアスは、エンプティコアが利用可能である時にハイパースレッド上にスレッドを同時スケジューリングしないように加えられる(ここで、pupuキュー上にvcpuを配置することで、vcpuが、対応するpcpu上で動作することになり、それによって、pcpu上でのvcpuの動作をスケジューリングする)。例えば、vcpu(ひいては、ストールしたvcpuにおいて実行中のゲストスレッド)は、それが実行した最後のpcpu上、または、同じコア上にはない最も近い関連物の上に配置されてよい。したがって、このように、ハイパースレッド上にキューアップされたvcpuがすでに存在する場合、新たな実行準備のできたvcpuは、同じコアを共有する次のハイパースレッド上には配置されない。
いくつかの実施形態において、トラバースの順序(キューの訪問の順序)は、起動時に固定され、システムの物理トポロジに対応する。
TTからPCPUへのVCPUのデキュー
TTからpcpuへvcpuをデキューする以下の例において、ゲストオペレーティングシステムが、クラスタにわたって集合的に実行されると仮定する。ゲストアプリケーションが、ゲストオペレーティングシステム上で実行している。ゲストアプリケーションは、次に、ゲストスレッドに関連付けられる。(vcpuが動作しているノード上のvcpuスレッドによって管理された)vcpuは、ゲストスレッドを実行する。
vcpuは、ハイパーカーネルのコンテキスト内に存在する。この例において、vcpuは、vcpuスレッド内で実行している。この例において、このvcpuスレッドは、実際にはFreeBSDスレッドであり、したがって、FreeBSDスレッドとしてFreeBSDによって管理されるが、ハイパーカーネルによってvcpuスレッドとしても管理される。任意のノード上で、vcpuスレッドとvcpuとの間の1:1の対応関係がある。一実施例において、所与のノード上で、vcpuスレッドとFreeBSDスレッドとの間の1:1の対応関係がある。一部の例において、ハイパーカーネルは、ハイパーカーネルがFreeBSDに依存して提供するスレッド以外にはスレッドを持たない。
仮想化システムが定常状態にあると仮定する。ゲストオペレーティングシステム(例えば、Linux)が、アプリケーションを実行している(例えば、読み出し、書き込み、計算を実行している、命令を実行している、プログラムカウンタを進めている、など)。例えば、アプリケーションに関連するゲストスレッドが、(ゲストオペレーティングシステムによって)vcpuに割り当てられており、vcpuは、物理プロセッサに割り当てられている。
ここで、物理プロセッサは、ゲストスレッドのために、命令を実行し、物理プロセッサにとって利用可能ではないメモリのページ(例えば、メモリのページが、物理プロセッサと同じノード上にない)にアクセスを試みると仮定する。例えば、仮想化ハードウェアは、(例えば、物理プロセッサが存在するノードのための第2レベルページテーブルを用いて動的アドレス変換を実行することによって)ゲスト物理ページ(そのアドレスは、上述のように、第1レベルページテーブルを用いて取得された)を、ホスト物理メモリ内の実物理メモリアドレスに変換しようとした。この例において、gpaのためのエントリがなく(例えば、第2レベルページテーブルのエントリが、無効化、ゼロ化などされており、gpaとノード上の実物理ページとの間のマッピングがない)、対応する実物理ページは、(vcpuスレッドによって実行され、ゲストスレッドに従事しているvcpuのアイデンティティを担っている)物理プロセッサによって解決または参照されることができないと仮定する。
仮想化ハードウェア(例えば、Intel VT−xまたはAMD AMD−V)は、gpaを実物理アドレスに変換できないので、割り込みが自動的に生成される。ハードウェアは、割り込みを生成する時、割り込みテーブル(オペレーティングシステムの一部)にアクセスし、割り込みテーブルは、割り込みが発生した時に呼び出されるルーチンのアドレスを含む。次いで、ハードウェアは、(例えば、対応するアドレスを用いることによって)ルーチンへベクトルする。例えば、プログラムカウンタ(および任意のその他のレジスタ状態)が、ハードウェアによって保存され(例えば、プロセッサの状態が割り込みスタックにプッシュされ)、新しいプログラムカウンタが、割り込みテーブル内で指定されたルーチンに設定される。割り込みルーチンを実行する前にプロセッサ状態を保存することにより、物理プロセッサは、割り込みから戻った後にその以前の状態に戻ることができる(例えば、割り込みから戻った後、保存された状態が、逆順に割り込みスタックから外され、それにより、プロセッサは、割り込み発生後に次の位置へ効果的にジャンプし、その結果、ゲストオペレーティングシステムは、割り込みが発生しなかったかのように継続する)。
この例において、呼び出される割り込みテーブル/ベクトルに含まれるルーチンは、ハイパーカーネルルーチン/コードである。いくつかの実施形態において、ホストオペレーティングシステムは、ハイパーカーネルに割り込みを送るよう構成されており(例えば、割り込みをハイパーカーネルに再ベクトルする)、ここで、ハイパーカーネルコードがその後に実行される。
発生時に割り込みを処理するために実行されるハイパーカーネルコードの例については、上述している。例えば、保存されたプロセッサ状態を用いて継続が生成されてよい(例えば、割り込みスタックを見ることができ、継続のために保存されたプロセッサ状態のスナップショットまたはコピーを取りうるハイパーカーネルコードによって)。ストールイベントが処理された後、vcpuの状態は、継続から復元されてよい(例えば、物理プロセッサがvcpuのアイデンティティを担うまたは引き受ける時に、vcpu内のプロセッサ状態をロードする)。
この例では、ストールが発生している。ストールは、すぐに扱うことができるもの、または、待つ必要があるもののいずれかでありうる。すぐに処理できるストールイベントの一例は、タイマーの要求である。タイマーが取得された後、ストールが処理され、割り込みが退けられてよい。
しかしながら、ストールが、例えば、(非ローカルページ要求による)ページストールである場合、ストールの処理は待機を必要とする。例えば、上述のように、1セットの多項式が、ストールを処理するための戦略を決定するために評価される。上述のように、ページを要求する決定がなされるか、または、メモリのページが存在するノードにvcpuをマイグレートさせる決定がなされるかのいずれかである。
例えば、ページの要求が送信されることが決定されると仮定する。vcpuスレッドは、この場合には待機しなければならない。その後、pcpuは、(vcpuのvcpuスレッド表現で実行中のゲストスレッドの)スレッドIDおよび継続へのポインタをイベントテーブル内に配置する。イベントテーブルに格納されたその他の情報は、vcpu(継続)が待っている要求されたページの識別子を含む。
したがって、上述のように、vcpuがストールすると、そのvcpuは、ゲストが物理プロセッサであると思っているが、ハイパーカーネルの視点からは、実際には仮想プロセッサ(すなわちvcpu)であるものにおいてゲストスレッドを実行していた可能性がある。ゲストオペレーティングシステム(例えば、Linux)内のスケジューラは、ハイパーカーネルの視点から、或る任意の根拠(すなわち、上述のように、スレッドコンテキスト切り替え)に基づいて、ゲストスレッドおよびvcpuのマッピングを変更しうるが、ゲストスレッド/vcpuの関連性は、ストール中には変化しえない。上述のように、ハイパーカーネルは、プロセッサ状態を調べることによってvcpuで実行中のスレッドのアイデンティティを追跡してよく、また、vcpuストール時にスレッド遷移イベントに気付きうる。vcpuは、上記イベントテーブルに関する議論において上述したように、すぐにストールを解消するために必要なことを実行してもよいし、ゲストが後に動作を完了できるように動作を開始する必要があってもよい。
例えば、後者のケースである場合、戦略決定(vcpuのマイグレートまたはページ要求の送信)がこのストールに対してなされ、これが遅延につながる(すなわち、ストールをすぐに処理できない)ことがわかると、上述のように、エントリがイベントテーブルに配置され、それが待っているイベントは、予定としてマークされる。ストールに対応する動作は、戦略代替の選択後に開始され(例えば、ページ要求を開始する、I/O動作を開始する、など)、(ストールしたvcpuを表す)vcpuスレッドは、イベントテーブル内の状態をポスト済みに設定する。
ここで、vcpuスレッドがイベントテーブルにイベントを入力した後、vcpuスレッドは、pcpuでまだ実行しているが、vcpuは(技術的に)実行していない(例えば、vcpuスレッドは、ハイパーカーネルコードを実行している)。次いで、vcpuスレッドを実行してきたpcpu(ここで、pcpuは現在では匿名プロセッサである)は、限られた量のハウスキーピング(例えば、メモリ利用のバランシング)を直接的または間接的に実行してよい。いくつかの実施形態において、vcpuスレッドは、ハウスキーピングスレッドに信号を送信して、ハウスキーピングをウェイクアップして実行する。あるいは、vcpuスレッドは、ハウスキーピング自体を実行してもよく、これは、コンテキスト切り替えの回数を削減する。
ハウスキーピングスレッドが実行できる作業量を制限するためのメカニズムが用いられてよい。このメカニズムは、ゲストによって行われる必要があるペンディングの作業の量によってパラメータ化されてよい。ペンディング作業の量は、例えば、実行準備のできたタイダルツリー内のvcpuの数によって特徴付けられてよい。これは、以下に提供される例で与えられうる:例えば、実行準備のできたvcpuが多くある場合、実行されるハウスキーピングは少ない。一方で、実行準備のできたvcpuが少数である場合、より多くのハウスキーピングが実行されうる。
//実行準備のできたTT内のvcpuの数を返す
n=runnable_vcpus();
ゲストオペレーティングシステムのために作業を実行するpcpuから、FreeBSD作業を実行するpcpuを分離することが望ましい場合がある。例えば、少数の物理プロセッサが、FreeBSDのために確保され(例えば、2であり、これは、起動時パラメータであってよい)、一方で、残りは、ハイパーカーネルのために確保されてよい。この責任の分割は、本明細書では「スケジューラ分割」と呼ばれる。上述のように、FreeBSDは、スレッドのスリープおよびウェイクアップを処理するために用いられてよく、ここで、FreeBSDは、所与のノード上のvcpuスレッドに対応するFreeBSDスレッドの適切な状態を保存および復元するよう注意しており、所与ノードは、vcpuに対応する。FreeBSDは、ハイパーカーネルのためにこれらの動作を自動的に(そして、おそらく、高度に最適化された方法で)処理する。ハイパーカーネルマイグレーションコードは、ノードおよびホストのスケジューラ限界にわたってこの動作をシミュレートする。
以下は、どのvcpuが現在の匿名物理プロセッサで動作するのか(すなわち、実行準備のできたvcpuを選択するか、または、TTから物理プロセッサへデキューするか)を選択する一実施例である。
イベントテーブルに配置されたばかりのvcpuを実行していたvcpuスレッドは、実際には、pcpuで実行している。pcpuで実行しているそのvcpuスレッドは、ここで、すでに実行準備のできたタイダルツリー内の待機中のvcpuを(もしあれば)選択してよい。例えば、以下のデキューアルゴリズムは、vcpuスレッドを実行する(現在は匿名/利用可能である)pcpuによって実行される。
匿名物理プロセッサ上で実行するvcpuの検索は、匿名物理プロセッサに対応するpcpuキューで開始される。上述したエンキュー/スケジューリングアルゴリズムと同様に、概念ツリーは、キャッシュラインを再利用するために上方へトラバースされる。上述のように、vcpuが、タイダルツリーに配置されると、vcpuが最後に動作したpcpuのキューにvcpuを配置する試みがなされる。現在の匿名pcpu(任意のvcpuスレッドとは無関係に、ハイパーカーネルコードを現在実行している)は、最も最近にpcpu上で実行していた実行準備のできたvcpuを検索するために、独自のキューをスキャンする。現在の匿名pcpuは、スキャニングを実行するためにFreeBSDスレッドを実行中であってよい(一方で、担うべき新しいvcpuアイデンティティを検索している)。いくつかの実施形態において、匿名pcpuは、キャッシュの温かさによってそのpcpu上で最後に動作したノード上のvcpuを選択するよう試み、ここで、最後に匿名pcpu上で実行していたvcpuの選択は、最も温かいキャッシュの再利用を可能にする。例えば、各物理プロセッサは、トランスレーション・ルックアサイド・バッファ(TLB)およびページのためのキャッシュラインエントリなど、1または複数レベルのキャッシュを有する。探されているページがすでにキャッシュ内にある場合、メモリ内でそれを検索する必要はない。匿名pcpuのキューが、実行準備のできたvcpuを全く持たない場合、例えば、概念的なキャッシュ階層順位に従って、その他のキューが次に検討される。
本明細書に記載の順位訪問の理由の一例は、以下の通りである。マルチコアプロセッサが、4つのコアを有すると仮定する。各コアは、キャッシュを有する。2つのマルチコアプロセッサがあり、各々が4つのコアを有する場合、pcpuは、それが一部を形成するマルチコアプロセッサのためのキューに留まることが好ましい。なぜなら、その後に共有キャッシュを利用できるからである(すなわち、別のコアのためのキューが利用される場合よりも、キャッシュラインを再利用できる可能性が高くなるので、物理的なローカリティを有するコアを用いる方が有利である)。これは、ハードウェア構成を調整する(ここで、ハードウェア構成は、図2に関連して記載したように、ツリー構造または階層として記載されてよい)。pcpuのノード上のすべてのpcpuキューがエンプティである場合、いくつかの実施形態において、pcpuは、すべてのノード上のすべてのpcpuにとってグローバルにアクセス可能なルートキューを検索する。これは、すべてのノード上の活動のバランスを取るのに役立つ効果を奏する。ルートキューもエンプティである場合、pcpuは、ハウスキーピングなど、他の処理を実行するよう構成されてよい。
いくつかの実施形態において、同じコア上の2つのハイパースレッドは、同じプロセッサハードウェアを共有または利用していることで、潜在的に互いの実行との衝突を引き起こす場合があるので、それらのハイパースレッドは、連続的にスケジュールされない。
実行準備のできた待機vcpuの選択後に、pcpuは、選択されたvcpuのアイデンティティを引き受ける。例えば、pcpuキューで最も長く待っているvcpuおよび/または最も温かいキャッシュアフィニティが、タイダルツリーから外される(例えば、最も長く待機しているvcpuになる第1vcpuが、FCFSリスト/キューから外される)。また、どの継続がハイパースレッドに割り当てるのに最も適切であるかを決定するために、コスト関数が用いられてもよい。いくつかの実施形態において、vcpuスレッドは、選択された待機中vcpuをウェイクアップするために信号を送信し、その後、自身をスリープさせて、それが完了を待っているイベントテーブル内のイベントを待つ。選択されたvcpuの状態は、pcpu上に復元される。この例において、このスリープ動作は、ホストスケジューラの暗黙的な呼び出しであり、FreeBSDスケジューラが、pcpu(そこで、vcpuスレッドが他の目的(例えば、ハウスキーピングスレッド、または、新たに起こされたvcpu)で実行していた)を利用することを可能にする。FreeBSDは、別のpcpuを選択して利用してもよい。上述の信号送信/ウェイク動作は、ハイパーカーネルが同期的にFreeBSDスケジューラを呼び出す明確な時点の間にある。
実行準備のできたvcpuがノード上にない(すなわち、ノード上のキューのためのすべてのpcpuキューがエンプティである)場合、pcpuは、自身をアイドル状態にしておかないことが好ましい。その代わりに、それは、ルートからvcpuを選択することが好ましい。pcpuで実行する以前のvcpuがストールして、イベントテーブルに配置された後に、作業を検索することにより、pcpuは、最大限にビジーに維持される(vcpuのストールイベントが解消されるのを待つのではなく、pcpuは、実行すべき新たな作業を検索する)。ルート上にvcpuがある場合、一実施形態において、上述したデキュー/vcpu選択アルゴリズムは、(ローカルノードのpcpuキュー上またはグローバルアクセス可能なルート上のいずれかで)実行準備のできたvcpuが見つかるまでループされる。別の実施形態において、別のノード上に実行準備のできたvcpuが存在する場合、ワークスチーリングが実行されてよく、ここで、他のノードが、vcpuの実行のためにクエリされ、1つはpcpu上で実行するためにノードから「盗まれる」。それが失敗した場合、pcpuは、ポッド/クラスタのどこにも、実行すべき作業を全く見出すことができないので、停止されて、電力を節約するために節電モードにされる。いくつかの実施形態において、pcpuは、最大限にビジー状態を維持するために、ハウスキーピングの実行を課せられる。
したがって、上述のように、pcpuが利用可能になると(すなわち、イベントテーブルにvcpuが格納されたため、vcpuマイグレーションが発生するため、もしくは、スタートアップまたはシャットダウン時に、vcpuの実行を停止すると)、実行するのに最も適したvcpuを探して、pcpuキューが検索される。ノードに、実行準備のできたvcpuが完全にない(すなわち、ノードに関連するpcpuキューがエンプティである)場合、第1vcpuは、TTのグローバルルートをプルされ、そのpcpu上で復元される。
複数の戦略が、タイダルツリーからどのvcpuをプルまたはデキューまたは他の方法で選択するのかを選ぶために用いられてよい。いくつかの実施形態では、コスト関数が、最高利益の戦略に到達するために用いられる。考慮すべき因子の例は、以下を含む。
1.スタベーションを避けることが好ましい。
2.ローカリティーゲストスレッドをプルしているノード上でのプルされたゲストスレッドのメモリ状態が参照されてよい。
3.最少可能数のノードにvcpu負荷を圧縮する試みがなされる場合、(vcpu負荷に)不必要ないくつかのノードが、含められずに除外されてよい。
オーバーコミットメントに関するさらなる詳細
いくつかの実施形態において、利用可能なvcpu(すなわち、実行準備のできたvcpu)の各pcpuキューの最大長は、調整可能である。キュー長は、起動時に固定されてもよいし、動的に調節可能であってもよい。最大キュー長の決定の一例として、pcpuの数がvcpuの数に等しいことが望ましいと仮定する。最大キュー長は、vcpuの数に制限されうるが、これは、システム内のすべてのvcpuが単一のpcpu上にキューアップできることを意味する。いくつかの実施形態において、ノードあたりp個のpcpuがあるn−ノードポッドの均一な分散を促すために、pcpuあたりの最大キュー長が、以下の式に従って決定されてよい。
pcpuあたりの最大キュー長=((vcpuの数)/n)/p
幅広い作業負荷のベストパフォーマンスを提供するキュー長を決定するために、実験を行ってもよい。
データ構造の例
p個のpcpuがハイパーカーネルに割り当てられている仮想化システムを仮定し、ここで、p個のpcpuは、n個のノードに分散されている。各ノード上の各pcpuに対応して、実行準備のできたvcpuのキューが存在する。最初、キューはエンプティである。いくつかの実施形態において、各pcpuは、さらに、起動時に固定されたパターンで検索すべき次のpcpuを特定する。いくつかの実施形態において、検索は巡回検索であり、ここで、この例においては、検索は、2つのパラメータ(現在のpcpuおよび開始点)で開始する。検索が開始点に戻ると、すべてのキューが訪問されたことになる。
物理プロセッサが各ノード上で開始すると、それらのプロセッサは、取り組むべきvcpuを探す。最初に、物理プロセッサは、ローカルに(例えば、ノードにローカルなpcpuキュー上を)探し、次いで、グローバルに(例えば、グローバルアクセス可能な「ルート」キューで)探す。タイダルツリーのルートをオーバーロードしないように、スタートアップ時に注意することが好ましい。
ハウスキーピング関数
上述のように、例えば、先述のタイダルツリーメカニズムが準備されていると仮定すると、vcpuスレッドが、そのvcpuをETに配置した後に、様々なハウスキーピング関数を直接的または間接的に呼び出してよい。
いくつかの実施形態において、ハウスキーピングは、(別のFreeBSDスレッドとして実装されてよい)バランサスレッドを介して実行されてよい。実施形態の一例において、バランサスレッドは、単一の同期スレッドである。バランサスレッドは、メモリの量を追跡し、他のハウスキーピング関数を実行してよい。バランサスレッドは、上述したサンプリングを実行するために用いられてもよい。バランサスレッドによって取られる動作は、利用度によって決まりうる。一実施形態において、利用度は、以下の3つのレベルに分類される:低、高、および、危機的。
バランサは、1または複数のpcpuによって非同期的に実行されてよい。pcpuは、匿名である間(すなわち、以前のvcpuエンティティを脱した後で、新しいpcpuのアイデンティティを担う前)、或る程度のハウスキーピングを実行してよい。これは、(オーバーロードになりうる1つのスレッドだけでなく)様々なpcpuにハウスキーピング作業負荷を分散させることを可能にする。
pcpuによって実行されるハウスキーピング作業の量は、様々な要素に応じて様々でありうる。一例として、pcpuによって実行されるハウスキーピング作業の量は、上述のように、実行するためにキューアップされたvcpuの数の合計に依存する。実行準備のできた多数のvcpuが存在する場合、ハウスキーピングの量は最小限に抑えられることが好ましい。キューアップされたvcpuが多数ではない場合、より多くのハウスキーピングがpcpuによって実行されてよい。これは、pcpuが、最大限にビジーなままで有用な仕事をすることを可能にする。
したがって、バランサが行うことを許される追加の作業の量は、制限されている。例えば、ノードが、実行準備のできた多数のvcpuで過密状態である場合、ハウスキーピングコードは、この情報(すなわち、実行準備のできたvcpuの数)を用いて、それに従って自身を制限してよく、その結果、pcpuは、例えば、vcpuのためのコンテナとして利用できるようになる。上述のように、バランサは、いくつのvcpuがタイダルツリーにあり、したがって、実行準備ができているのか、を示す情報を提供される。実行準備のできたvcpuが少数であると、バランサは、より多くの時間をハウスキーピングに費やし;多数であると、バランサは、より少ない時間をハウスキーピングの実行に費やす。
実行されるハウスキーピングの一例は、危機的なメモリ利用レベルの時に(例えば、上述のように、メモリ圧迫が危機的な状態にある時に)、ページを取り除くかまたはエビクトすることである。上述のように、メモリ管理が実行されてよく、メモリ管理は、各ページについて、どのスレッドがページを必要とするのかを追跡すること、および、各スレッドについて、どのページを必要とするのかを追跡することを含む。どのページをエビクトするのかは、かかる情報および優良度メトリックに基づいて決定されてよい。例えば、エビクトに向けてページを評価する時、ページを必要とする各スレッドの優良度メトリックが決定されてよい。例えば、ページを利用しているスレッドが良好に実行している場合、他の条件が全て同じなら、ページはおそらく、エビクトされないことが好ましい。対照的に、スレッドの挙動が悪いページは、エビクトされてよい。
いくつかの実施形態において、以下のコールはいずれも、ステータスを返さない(一部の例において、それを終わらせうるものがないため)。いくつかの実施形態において、コールは、タイダルツリーからアクティブ化する次のスレッドを選択する機会を許すことなしに、FreeBSDスケジューラを含めさせる任意のコード(例えば、waitなど)を呼び出すことを妨げられる。
//いくつかの実施形態において、このコード例は、VCPUを別のノードへ送信する前に呼び出され、
//ハウスキーピングコードがハウスキーピング処理(予めページを移動するなど)を
//実行することを可能にする。
//この例において、ts_load_hintは、システムがビジーである(そして自身を制限する)こと、または、
//システムがビジーではないことを、
//ハウスキーピングコードに示す列挙型(enum)である。
void ts_housekeeping_on_vcpu_move(int vcpuid, void *arg, ts_load_hint hint)
//いくつかの実施形態において、これは、イベントテーブルにVCPUを配置した後に呼び出される。
void ts_housekeeping_incremental(ts_load_hint hint)
以下は、ハウスキーピングシステムが決定を行う場合の一連の事例を規定しており、ここで、本明細書に記載のコスト項の内の1または複数が利用されうる。
動作すべき時の選択の例:ハウスキーピングは、常に起きる必要がない場合がある。ハウスキーピング関数が、例えば、多すぎるページを送り出すことによって「過剰反応している」場合、これは、潜在的にメモリ断片化を引き起こしうる。一方で、ハウスキーピングが十分高速に動作しない場合、メモリ圧迫により、あまりに多くのvcpuマイグレーションが余儀なくされていることがある。様々な実施形態において、メモリ容量の推定、アクティブなスレッド/vcpuの数、および、IOの頻度が、動作すべき時、および、エビクトされる必要があるページの数の決定を容易にするために用いられる。
エビクトすべきページの選択の例:いくつかの実施形態において、バランサは、或る短期間内に特定の数のページをエビクトする(例えば、過度のメモリ圧迫を避けるために)。メモリ状態、優良度、共通関心などの項からの入力が、そのノード上のゲストスレッドに関連してノード上の「最も低い」有用性のページをエビクトするため、または、例えば、そのノード上の最低の優良度のゲストスレッドに有用な1セットのページをエビクトするために用いられてよい。様々な代替例が実施されてよい。
エビクトされる宛先の選択の例:いくつかの実施形態において、メモリは、必要以上に分散されない。他のノードの容量に関する情報が、自身のバランシングの問題を持たないノード上にメモリを移動させる際にバランサを支援するために用いられてよい。
図15Cは、ストールイベントに対処するための処理の一実施形態を示すフローチャートである。いくつかの実施形態において、処理1520は、ハイパーカーネルによって実行される。処理は、物理プロセッサにおいて動作する仮想プロセッサに関連するストールイベントの示唆が受信される工程1522で開始する。ストールの一例は、非ローカルページ要求によるものである。
工程1542で、ストールイベントがすぐに対処されうるか否かが判定される。ストールイベントがすぐに対処されうる場合、工程1526ですぐに対処され、処理1520は終了する(ここで、仮想プロセッサは、ストールの迅速な対処の後に物理プロセッサで動作し続ける)。
ストールイベントがすぐに対処されえない場合、処理は、工程1528へ進み、ここで、仮想プロセッサはイベントテーブルに配置される。例えば、ストールイベントが、非ローカルページアクセスが原因であるために、すぐに対処されえないと仮定する。この例では、ページの要求が送信される。次いで、vcpuは、イベントテーブルに配置され(ここで、例えば、その継続がイベントテーブル内に配置される)、そこで、要求されたページを待つ。イベントが発生するかまたは満たされると、仮想プロセッサは、イベントテーブルから外され、タイダルツリー(例えば、図15Eの処理1560を用いて、図15Aのタイダルツリー1500)上に配置またはエンキューされる。vcpuをイベントテーブルから外して、vcpuをタイダルツリー上にエンキューすることは、pcpu上でのvcpuの実行を効果的にスケジューリングする(vcpuは、最終的には、pcpuが匿名になって作業を検索した時にpcpuによって実行されるため)。
仮想プロセッサを実行していた物理プロセッサは、もはや、vcpuを実行しているとは見なされず、現在は匿名である。処理は、工程1530へ進み、ここで、物理プロセッサが実行するために、実行準備のできた仮想プロセッサが選択される。実行準備のできた仮想プロセッサを選択するための処理の例は、図9の処理900および図15Dの処理1540を含む。工程1532では、選択された仮想プロセッサは、物理プロセッサ上に復元される(ここで、物理プロセッサは、選択された仮想プロセッサのアイデンティティを担い、もはや匿名ではなくなる)。
いくつかの実施形態において、工程1530の前に(例えば、pcpuが匿名になった時から、pcpuが次のvcpuアイデンティティを回復する時までの間)、物理プロセッサは、上述のように、ハウスキーピングを実行するよう割り当てられてよい。ハウスキーピング作業が完了すると、処理は、工程1530に進む。
図15Dは、実行準備のできたvcpuを検索する処理の一実施形態を示すフローチャートである。これは、vcpuをタイダルツリーから物理プロセッサへデキューする工程を含んでよい。いくつかの実施形態において、処理1540は、ハイパーカーネルによって実行される。いくつかの実施形態において、処理1540は、図15Cの処理1520の処理工程1530および1532を実施するために用いられる。
処理は、ストールイベントの示唆が受信される工程1542において始まる。ストールイベントは、ノード上の物理プロセッサで動作する仮想プロセッサに関連する。ノードは、複数の物理プロセッサを備える。ノードは、ノードのクラスタに含まれており、クラスタにわたって、ゲストオペレーティングシステムが集合的に実行される。いくつかの実施形態において、工程1542は、図15Cの工程1522の一例である。
工程1544で、ノード上の物理プロセッサに対応する1セットのキューで、実行準備のできた仮想プロセッサが検索される。物理プロセッサに対応するキューのセットの例は、図15Aに関連して上述したpcpuキューである。セット内のキューは、概念的なキャッシュ階層順位に従うように検索される。例えば、セット内のキューは、上述のように、所定のトラバースアルゴリズムに従って検索されてよく、ここで、キューの訪問の順序は、キャッシュアフィニティに対応し、ツリーウォークを模倣する。いくつかの実施形態において、訪問および検索される最初のキューは、ストールした仮想プロセッサを実行していた現在は匿名である物理プロセッサに対応するキューである。
実行準備のできた仮想プロセッサが、ノード上の物理プロセッサに対応するキューのセット内で見つからない場合、クラスタ内の複数のノードにとってグローバルにアクセス可能なルートキューの検索が実行される。
工程1546では、実行準備のできた仮想プロセッサが、検索に基づいて選択される。例えば、トラバース順序で訪問される最初の非エンプティキューの先頭の仮想プロセッサが選択される(ここで、キューはFCFSである)。いくつかの実施形態において、実行するのに(例えば、匿名物理プロセッサに割り当てるのに)適切なvcpuが、コスト関数に基づいて選択される。例えば、最も長い時間にわたってキューに入れられていた継続が、割り当てられうる。選択された仮想プロセッサは、物理プロセッサに割り当てられる(例えば、物理プロセッサ上に復元され、ここで、物理プロセッサは、選択された仮想プロセッサのアイデンティティを担う)。
図15Eは、実行準備のできたvcpuをタイダルツリーに配置するための処理の一実施形態を示すフローチャートである。これは、vcpuをタイダルツリー上にエンキューする工程を備えてよい。いくつかの実施形態において、処理1560は、ハイパーカーネルによって実行される。
処理は、仮想プロセッサの実行準備ができている旨の示唆が受信される工程1562において開始する。示唆は、仮想プロセッサが待っていたイベントが発生したことに応じて受信されうる。仮想プロセッサは、それが待っていたイベントが発生した結果として、イベントテーブルから外される。一例として、ストールしたvcpuがページを要求したと仮定する。ページは到着し、ストールしたvcpuが待っていたイベントを満たす。例えば、ページが到着すると、イベントテーブルは、どのvcpuがページ(それのゲスト物理アドレスなど、それのリソース識別子によって識別される)を待っていたのかを決定するためにアクセスされる。仮想プロセッサ(およびページを待つ任意のその他のプロセッサ)は、実行可能にされる。
工程1564では、仮想プロセッサを配置するキューが、少なくとも部分的には、ノード上の1セットの物理プロセッサに対応する1セットのキューをトラバースすることによって決定される。例えば、上述のように、キューの物理ツリーとして実装されたタイダルツリーが検索される。別の例として、タイダルツリーは、実行準備のできたvcpuのキューのラインまたはセットとして実装され、ここで、ハイパーカーネルに割り当てられた各物理cpu(「pcpu」)に1つのキューがあり、物理タイダルツリーの階層は、訪問順序に置き換えられる(例えば、図15Aに関連して記載したような最適化タイダルツリー)。いくつかの実施形態において、訪問される最初のキューは、仮想プロセッサが最後に動作していた物理プロセッサに対応する。上述のように、仮想プロセッサの状態(例えば、継続)は、それが動作していた最後の物理プロセッサを示すよう拡張されてよい。pcpuがオーバーロードにならない限り、vcpuは、キューに配置される。最初のキューが満杯またはオーバーロードであった場合、トラバースは、固定されたトラバース順序に従って、セット内のその他のキューに進む。いくつかの実施形態において、トラバース順序は、システムトポロジによって規定される。トラバース順序は、ツリーウォークを模倣する(例えば、概念ツリーのウォーク)。
物理プロセッサキューが満杯でない場合、仮想プロセッサは、物理プロセッサキュー上に配置される(例えば、キューの最後すなわち尾部に配置され、ここで、キューはFCFSである)。したがって、現在作業を探している次のpcpuは、自身がそれになりうるさらなるvcpuを検討する必要がある。だから、次のvcpuがストールすると、ストールしたvcpuを実行していたpcpuは、ページ到着の結果としてキューに配置され、最も温かいキャッシュを有し、(キュー上に他のvcpuがすでに存在しうるため、いつかの時点で)新たなvcpuになる次のvcpuを選択する。上述のように、一実施形態において、pcpuキューは、外されるvcpuが、最も長い時間にわたってキューの中にあったvcpuになるように、FCFSまたは先入れ先出し(FIFO)である。非FIFOの戦略が用いられてもよい。次いで、コンピュータシステムは、半自動的に自身を最適化してよい。
ノードの物理プロセッサに対応するキューがすべて、満杯である(および、実行準備のできた仮想プロセッサを配置する物理プロセッサキューがない)場合、一実施形態において、vcpuは、クラスタ全体からグローバルにアクセスでき、任意のpcpuがアクセスできるキュー(「ルート」と呼ぶ)上に配置される。一例として、ルートキューは、クラスタのノード間のプロトコルを通してクラスタ全体にわたるすべてのpcpuからグローバルにアクセスできるようになっている(例えば、ここで、ルートの内容はブロードキャストされる)。
上記において、vcpuは、ノード上のすべての他のキューが満杯であったために、ルート上に配置された。これは、ローカリティに影響を与えうるため、最も最適な決定ではない場合がある。例えば、所与のノード(例えば、vcpuが最後に動作していたノード)上で、vcpuは、(例えば、優良度メトリックによって測定して)非常に良好に機能していた可能性がある。別の実施形態において、ルートキュー上にvcpuを配置する代わりに、ノード上のキューのセットにおいて最もパフォーマンスの低いvcpuが識別され、それの物理プロセッサキューからエビクトされる。一例として、最もパフォーマンスの低いvcpuは、上述のように、優良度メトリックに従って決定される。次いで、エビクトされた仮想プロセッサは、実行準備のできた仮想プロセッサのルートであるグローバルアクセス可能なキューに配置される。次いで、実行準備のできた仮想プロセッサは、エビクトされた仮想プロセッサが除去された物理プロセッサキュー上に(例えば、その最後に)配置される(すなわち、vcpuがノード上で良好に実行する場合、それほど良好に実行しないノード上の実行準備のできたvcpuが、パフォーマンスの良好なvcpuへキュー内の場所を明け渡すことが好ましい)。したがって、上述のように、キューにvcpuを配置しようとする時に、その優良度は、他のvcpuの優良度と比較される(ストールしたvcpuにあるスレッドの優良度と比較する)。次いで、ノード上において優良度で最も悪いパフォーマンスのvcpuは、ルートへ移動される。したがって、配置されているvcpuが、ノードのキュー内の別のvcpuよりもノード上で良好なローカリティを有する場合、よりパフォーマンスの悪いvcpuがノードから移動され、ルートキューに配置される(すなわち、vcpuにおいて実行している最も優良度の低いスレッドが、ルートキューへエビクトされるよう選択されたスレッドである)。
いくつかの実施形態において、トラバースアルゴリズムは、エンプティコアが利用可能である時に、ハイパースレッド(pcpuキュー)上へスレッドを同時スケジューリングしないようにバイアスされる。
いくつかの実施形態において、キューが長くなりすぎないように、オーバーロード閾値が実施される(例えば、キュー上に最大で3つのvcpu)。オーバーロード閾値は、起動時パラメータであってよい。例えば、ノード上のすべてのpcpuキューが満杯であると仮定する。例えば、キューの長さは合わせると、ノードが対応できるよりも長くなる場合がある。例えば、ノード上に複数のpcpuがあると、2倍、3倍、ないし、10倍の数のvcpuが存在しうる。オーバーロード閾値は、優良度メトリックと共に、ノード上の最もパフォーマンスの低いvcpuをルートキューへエビクトさせる。これは、プロセッサを分散させ、フロッキング/オーバーロードを防止する利点を有する。また、この結果、ページとのローカリティを形成することになる(すなわち、ワーキングセットを構築する)。また、仮想化システム全体の負荷が、需要駆動でバランスされうる。
上述の実施形態は、理解しやすいようにいくぶん詳しく説明されているが、本発明は、提供された詳細事項に限定されるものではない。本発明を実施する多くの代替方法が存在する。開示された実施形態は、例示であり、限定を意図するものではない。