サイト内の現在位置

VEOSの機能(その1)

no.0032020.09.30

 SX-Aurora TSUBASA とは何か?と聞かれるとラックがいくつも並ぶ大規模なハイパフォーマンスコンピューターというイメージが湧くかもしれません。ウソではありませんがそれがすべてではありません。一番小さなモデル、タワーサーバーモデルの中を覗いてみると赤いカードが一枚と、X86 processorがまず目に入ります。このX86 processorではLinuxが動いています、見えませんが。
 実はSX-Aurora TSUBASAの前モデルまではSUPER-UXという名前の、NECでHPC向けに手を入れたUNIX系専用OSが使われていました。いまでも、WEBで次の一文を見ることができます。

高性能ベクトルクラスタのハードウェア性能を、極限まで引き出すオペレーティングシステムとして「SUPER-UX」を提供します。

出典:https://jpn.nec.com/hpc/sxace/index.html


 WikipediaでSUPER-UXを検索すると、次のようなとても簡潔な一文が見つかります。

UNIX系OSですが、HPC用途に機能が追加されたOSです。
(SUPER-UX is a 64-bit UNIX operating system.)
出典:https://en.wikipedia.org/wiki/SUPER-UX


 SX-Aurora TSUBASAでは専用OS SUPER-UXの代わりに汎用的に使われているLinuxを使って赤いベクトルカードをコントロールする方法を選びました。Linuxなら広く一般に使われている開発ツールがそのまま使えますし、shellも挙動について馴染み深いものを選ぶことができて、色々と良い点があります。ですが、Linuxが動くCPUとは別の場所(赤いカードの中のベクトルprocessor)でプログラムを実行させるためには一工夫も二工夫も必要になります。
 では、SX-Aurora TSUBASA の汎用Linuxはどのようにしてベクトルカードをコントロールしているのでしょうか。今回はその点を見ていきたいと思います。

 まず、x86とPCIのパイプで結ばれる赤いベクトルカードの関係をハードウェア視点から見るために、PCIデバイスの情報を表示するlspciコマンドを実行してみましょう。lspciコマンドはLinuxのshellと対話しながら実行します。出力結果を見てみるとSATAやUSBコントローラーの他、数多くのPCIに接続されているデバイスが列挙されます。その中に、赤いカードVector Engineの名前を見つけることができました。ここで気になるのはCo-processor。赤いカード(ベクトルカード)はCo-processorなんだそうです。

fig.-1 lspciを使ってVEカードを表示
fig.-1 lspciを使ってVEカードを表示

 ここでCo-processorについて再びWikipediaで調べてみると次の一文が出てきます。Co-processorとはあくまでCPUが行う処理の一部をオフロードして、浮動小数点演算やグラフィックス処理など行う、”サプリメント”な存在だとあります。

 A Co-processor is a computer processor used to supplement the functions of the primary processor (the CPU). Operations performed by the Co-processor may be floating point arithmetic, graphics, signal processing, string processing, cryptography or I/O interfacing with peripheral devices. By offloading processor-intensive tasks from the main processor, Co-processors can accelerate system performance.

出典:https://en.wikipedia.org/wiki/Coprocessor


 一定の年齢層以上にしか通じないかとは思いますが、かつてPC-9801に8086(V30)というprocessorが載っていました。そして別売りの8087という浮動小数点演算用Co-processorが存在していたのです。いまとなっては当時の値段が思い出せませんが、相当高かったような記憶があります。

 lspciの出力から、LinuxはSX-Aurora TSUBASAのベクトルカードをPCI経由でCPUを補佐するCo-processorとみなしていることが分かりました。しかしSX-Aurora TSUBASAではC/C++やFortranで書かれたコードをベクトルアーキテクチャ用コンパイラで実行ファイルに変換し、一連の処理を頭から最後までベクトルカード上で実行できなければなりません。
 ベクトル化された数値演算はもちろんですが、データをディスクからベクトルカードのメモリに読み込んだり、結果を標準出力に表示させたりすることも求められます。はっきり言ってCo-processorがオフロード処理する枠を超えた活躍が求められます。
 では実際にどのようにしてホスト側のCPUから処理をベクトルカードにオフロードしてユーザーのアプリケーションを丸ごと実行させているのか、その裏側で行われている動きについて見ていきたいと思います。

- VH-VEの仕組み VEOSの役割

 SX-Aurora TSUBASAのホスト側(以降VH)のCPU上ではCentOSやRedHatといったLinuxが動作し、その中にはカーネルといういわばユーザーのプログラムとハードウェアの仲介役が存在しています。仲介役であるカーネルはユーザープログラムが出す要求、例えばどこそこのメモリにアクセスしたいとか、画面に結果を表示したい、といったリクエストを受けてハードウェアに実際の動作を指示します。このリクエストは実際にはシステムコールという形でカーネルは受け取ります。ここまではVH側での処理についての説明ですが、VE一人では結果を画面に表示したり、ディスクに書き出したりすることはできません。さて、PCIの先につながれたベクトルカード(以降VE)で実行されるユーザープログラムはどのようにしてVH側で動いているカーネルにリクエストを出しているのでしょうか。

 VH側のリソースを使わせてもらうためには、やはりVHのカーネルに一言断りを入れた上で処理をお願いすることになりますが、では、カーネルがVE上で実行されるユーザープログラムのリクエストに直接応えてくれるかというと、そう都合のいいように事は運びません。カーネルにしてみればPCIの先にあるCo-processorでなにやらプロセスが勝手に動いていて、それが聞いたことない言語で話しかけてきて、ちょっと画面使わせてくれとか、ディスクにもの置かせてくれと言ってきても相手にするわけにはいかないからです。
 例えるならば、寒い冬の日、子狐がどんぐり(リクエスト)を手にカーネルのところにやってきて手袋ほしい、代金はどんぐり、というようなものです。カーネルには子狐が言っていることが分かりません。そこに現れたのはカーネル長屋の住人、VEOSです。VEOSは狐語が理解できます。また、カーネルとシステムコールという言葉で会話もできます。VEOSは間に入って通訳し、カーネルに手袋作ってほしいとお願いします。子狐は手袋(処理結果)を手に引き上げていきます。このたとえの中でVEOSはカーネル長屋の住人といいましたが、SX-Aurora TSUBASAのVHにあるLinuxの上で動作するプログラムです。VEOSにはVEOSデーモンをはじめとしたいくつかのデーモンやVEOS用に移植されたpsやfreeなどのコマンドが含まれています。

 では、実際にpsを使ってVEプロセスがLinuxからどのように見えているのか確認してみましょう。

fig.2 LinuxのpsでVEOSを確認
fig.2 LinuxのpsでVEOSを確認

fig.2に示すようにLinuxのpsを実行しVEOSのプロセスを表示しました。(VEで動くプロセス状況を確認するためにVE用psがあります。これは後で出てきます。)カーネル上で動く多くのプロセスの中にVEOSが含まれていることが分かります。この場合ではVEOSには2056という番号(プロセスID、以降pid)が付けられていて、他のプロセスと区別できるようになっています。

 では、VEOSの正体はいったい何なのでしょう。VE上で動作するプログラムのプロセス管理・メモリ管理を行うという意味から、VE視点でVEOSはOSそのものなのです。そしてVEOSはVEの世話をするために存在するものです。
 一方、カーネルにしてみるとVEOSはプロセスの一つです。VEOSはVEカード上で動くユーザープログラムからのリクエスト(画面に文字を出力したい、とかVHのハードウェアを使わせてほしいというもの)をカーネルに伝える代理人(正確にはve_execというコマンドを実行して作られる代理プロセスがその仕事を行います。)です。さすが、代理人、狐語が分かるだけでなくもっと重要かつ様々なことができます。

 fig.3にVEのためにVEOSが世話を行う処理内容を示しました。

fig.3 VEOSが行う処理の内容
fig.3 VEOSが行う処理の内容

 まず、VEOSの機能の中からプロセス管理についてみていきましょう。
 ここでのプロセスとはVEで実行されているユーザープログラムを指します。では実際にVEとVHでpidを表示させるユーザープログラムを実行し、VH側のpsでどのように見えるか試してみます。このユーザープログラム(hello_getpid_ve.exe, hello_getpid_vh.exe)はそれらプログラムの中でgetpid()というシステムコールを出して自らのpidを要求して表示するようになっています。

 fig.4の通り、VE上のプログラムhello_getpid_ve.exeにつけられたpidは97189、VHで実行するプログラムhello_getpid_vh.exeのpidは112422です。VHのLinuxのpsはそのどちらも表示していることが分かります。

fig.4-1 VEのプロセスをLinuxのpsで確認
fig.4-1 VEのプロセスをLinuxのpsで確認

fig.4-2 VHのプロセスをLinuxのpsで確認
fig.4-2 VHのプロセスをLinuxのpsで確認

 少し違うのは、VHのプログラムはシンプルに./hello_getpid_vh.exeとプログラム名が表示されているのに対して、VEのプログラムはve_execやVEOS0.sockといったプロセス名の後に実行プログラム名が出ている点です。
 実はカーネルの立場からはVEのユーザープログラムhello_getpid_ve.exeを実行するプロセスは直接見えておらず、ve_execというプログラムを実行するためのプロセス(代理プロセス)として見えます。
 先にも少し触れましたが、この代理プロセスve_execはVEへのユーザープログラムのロード、VEプロセスからのシステムコール要求処理などを行います。そしてカーネルはve_execという代理プロセスがCo-processor(VE)を使用している、と見ています。代理プロセスは間に入って必要に応じて「狐語」のシステムコールを、カーネルのシステムコールに通訳します。
 しかし、「VEのメモリに領域を割り当ててください」のように単純に通訳してもVHでは処理できないシステムコールもあります。カーネルはVEの中にあるメモリのことは関知していないのです。
 そこでVEOSはVEのリソースの面倒を一手に引き受けて、VEプロセスの登録、メモリの割り当て・管理といった作業を担うのです。97189というpidはve_execのプロセスのものであり、Linuxがつけた番号です。ve_execは後にVE上で実行されるプロセスの代理プロセスとなり、対となるVEのプロセスのPIDを同じPIDでVEOSに登録します。
 こうしてカーネルは自ら名付けた112422だけでなくVEOSが名付けた97189を子プロセスとしてその存在を知ることができるのです。そして カーネルはve_execを介して、VEプロセスの異常なメモリアクセスによる暴走や、正常終了できなくなっていないか気にかけているのです。さすがVEOSはカーネル長屋の管理人です。長屋の住人VEOSの関係者ことまで把握しています。

 では、先と同じプログラムhello_getpid_ve.exe, hello_getpid_vh.exeを実行してVE側のpsで見てみるとどうなるでしょう。
 fig.5-1と2にその結果を示します。今回のVE上プロセスのpidは94025です。VEOSのpsで表示してみると94025の名前が出てきます。しかし、VH上のプロセス95427はVEOSのpsからは出てきません。このことから、VEOSはVEで動いているプロセスだけを気にしている(管理している)ことがここから見て取れます。

fig.5-1 VEのプロセスをVEOSのpsで確認fig
fig.5-1 VEのプロセスをVEOSのpsで確認

fig.5-2 VHのプロセスをVEOSのpsで確認(psの結果表示ありません)
fig.5-2 VHのプロセスをVEOSのpsで確認(psの結果表示ありません)

次回に続く