情報畑でつかまえてロゴ
本サイトは NTTテクノロスが旬の IT をキーワードに
IT 部門が今知っておきたい最新テクノロジーに関する情報をお届けするサイトです

リソース設定(メモリ) ~DPDK入門 第4回~

DPDKでは高速化を実現するためHugePageというメモリ管理の機能を使っています。今回は通常のメモリ管理との違いを解説し、DPDKでのメモリを設定方法に関して紹介していきます。

はじめに

こんにちは、NTTテクノクロス株式会社の寺尾です。
今回はDPDKのメモリ設定に関して解説していきます。よろしくお願いします。

イメージ画像

メモリ管理

DPDKでは高速化を実現するためHugePageというメモリ管理の機能を使っています。HugePageを説明するために、一般的なメモリ管理の仕組みである「仮想メモリ」に関して解説します。

仮想メモリとは

仮想メモリとはOSやCPUが提供するメモリ管理の仕組みで、プログラムを動かすために必要なデータを主記憶装置に割り当てる機能です。プログラムは他のプロセスに関係無くメモリを連続した領域で割り当てたいのですが、コンピュータ上ではたくさんのプロセスが動いているため、実際には連続した領域を直接割り当てることができません。 そのため、OSはプログラムが利用できる仮想的な連続領域を「仮想メモリ」として提供する機能を持っています。以下にそのイメージを記載します。

OSはメモリをブロック単位で確保や解放を行い、「仮想メモリ」と実際のメモリとの対応関係を「アドレス変換テーブル」で管理することによって、他のプロセスの状態を気にすることなく、あたかも連続した領域が割当たっているようにプログラムを実行することができます。このブロックのことをメモリ管理ではページと言います。

「仮想メモリ」には、一次記憶装置であるメモリだけでなく、不足した領域を二次記憶装置で補う機能もあります。あまり利用されていないページを二次記憶装置に追い出すことで、新たにメモリを使えることが可能となります。追い出されたページはプロセスが利用する時にOSが再度メモリに配置するため、プロセスはメモリの状態を気にする必要がありません。

ただし良いことばかりではありません。デメリットとしては、アドレス変換テーブルは個々のプロセスがメモリの確保や解放にタイミング等で書き換えが必要になります。また二次記憶装置が利用された場合、メモリと二次記憶装置の間でページの入れ替えが発生します。これらの処理のため、性能面では不利になります。

HugePageとは

最近では物理メモリが安価になってきており、利用できる領域も大きくなってきました。現在では100GB以上のメモリを搭載するマシンも珍しくありません。ただ「仮想メモリ」では、管理するページ数が増えることになります。1ページのサイズはx86-64系システムなどでは4KBです。例えば、128Gbyteのメモリに対して、二次記憶装置の128Gbyteを加え、仮想メモリとして256Gbyteとした場合は、最大6400万ページ(256GB÷4KB)以上の管理が必要となります。ページ数が大きくなればなるほどOSやCPUの負担も大きくなります。

その課題に対しての解決策がHugePageになります。HugePageとは単語の意味通り「巨大」な「ページ」のことで、メモリ管理として1ページのサイズを大幅に拡張することを可能とした機能です。HugePageのサイズはx86_64系システムでは2MBや1GBがあります。HugePageに対応しているかどうかは、以下のコマンドでCPUの情報を確認します。

$ cat /proc/cpuinfo
・・・
flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ss syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon rep_good nopl xtopology cpuid pni pclmulqdq vmx ssse3 fma cx16 pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand hypervisor lahf_lm abm invpcid_single pti tpr_shadow vnmi flexpriority ept vpid fsgsbase tsc_adjust bmi1 avx2 smep bmi2 erms invpcid xsaveopt arat
・・・


flags に pse があれば2MBページ、pdpe1gb があれば1GBページのHugePageの設定が可能です。上記の例では、両方の記載がありますので、どちらでも設定ができます。

HugePageを使うと、ページサイズが増えることで仮想メモリアドレス変換テーブルが小さくなるため性能面で優位に働きます。またページイン及びページアウト処理が発生しないため、ページの入れ替え処理が発生するリスクがなくなります。ただし、メモリに対して大きな単位で割り当てるとともに、ページイン・ページアウトができないことから、メモリの使用効率は悪くなるデメリットがありますのでご注意下さい。HugePageのメモリアドレス空間と通常のメモリアドレス空間との違いに関して、そのイメージを示します。

仮想メモリアドレスと実際のメモリアドレスを変換する仕組みとして良く利用されるのがTLB(Translation Lookaside Buffer)です。仮想メモリアドレス変換テーブルは通常はメモリに配置されますが、さらに高速にアクセスできるCPU内部のキャッシュに変換情報を配置することで、高速な変換処理を実現しています。このキャッシュ領域は非常に小さいため、全てのページテーブルの情報を格納することはできません。変換処理としてはキャッシュ領域に配置されているTLBから変換処理を行うことを試み、情報が無ければメモリに配置している仮想メモリアドレス変換テーブルを用い変換処理を行います。効率よく変換するためには、いかにキャッシュ領域からの検索ヒット率を向上させるかが重要になります。HugePageはページテーブルのエントリ数が小さくなるため、キャッシュ領域からの検索ヒット率が向上し、性能面で優位に働いていきます。詳細は以下のサイト(※1)を参照ください。

※1 仮想メモリーを支えるもうひとつのキャッシュ TLB
http://ascii.jp/elem/000/000/567/567889/


HugePageの設定

HugePageの設定はファイルにページ数を更新するだけで可能です。今回は1CPUを搭載したマシンを例に解説をしたいと思います。念のため以下のnumactlコマンドで利用できるノードのメモリ量を確認下さい。numactlコマンドがもしなければ、以下のコマンドでインストール下さい。

$ sudo apt-get install numactl

numactl でハードウェア情報を出力します。

$ numactl -H
available: 1 nodes (0)
node 0 cpus: 0 1 2 3
node 0 size: 7976 MB
node 0 free: 7334 MB
node distances:
node 0
0: 10


available: 1 nodes と出力とされており、1CPUを搭載したマシンであることが確認できます。またメモリ量の総領域が 7976 MB で、空いている(free)領域は 7334 MBであることが分かります。メモリ量は/proc/meminfo の情報と合致することも確認できます。

$ cat /proc/meminfo
MemTotal: 8167448 kB
MemFree: 7510624 kB
MemAvailable: 7807124 kB
・・・

参考までに2CPUを搭載したマシンでは以下のように出力されます。

$ numactl -H
available: 2 nodes (0-1)
node 0 cpus: 0 2 4 6 8 10 12 14 16 18 20 22 24 26 28 30
node 0 size: 31942 MB
node 0 free: 22205 MB
node 1 cpus: 1 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31
node 1 size: 32244 MB
node 1 free: 21926 MB $ cat /proc/meminfo
MemTotal: 65727756 kB
MemFree: 45194960 kB
MemAvailable: 51064604 kB
・・・

複数のCPUが搭載された場合、複数のnode毎にメモリが存在していることを示しています。このようなアーキテクチャはNUMA(Non-Uniform Memory Access) (※2)と呼ばれ、現在は主流のアーキテクチャになっています。このようなマシンでは、HugePageの設定を詳細に指定でき、割り当てる方法も異なります。この話は別の機会で掲載したいと思います。

※2 CPUを複数持つアーキテクチャNUMAとnumactlの説明
https://qiita.com/bokotomo/items/5352b8ceb6ccb70390c8

それでは、2KBのHugaPageを1024ページ設定します。この作業はrootユーザで実施下さい。

# echo 1024 > /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages


設定されたかどうかは、以下のコマンドで確認できます。

$ cat /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages
1024
$ cat /sys/kernel/mm/hugepages/hugepages-2048kB/free_hugepages
1024


1024ページ設定され、すべてのページがfree状態であることが分かります。別のコマンドでも確認できます。

$ cat /proc/meminfo | grep -e Mem -e Huge
MemTotal: 8167448 kB
MemFree: 5257264 kB
MemAvailable: 5676312 kB
・・・・
HugePages_Total: 1024
HugePages_Free: 1024
HugePages_Rsvd: 0
HugePages_Surp: 0
Hugepagesize: 2048 kB
・・・・

HugePageが1024ページ確保された状況が、空(HugePages_Free)や総量(TotalHugePages_Total)の項目で確認できます。またメモリ容量では空きメモリ(MemFree/MemAvailable)から 約2GB分の容量が減っていることも確認できます。尚、HugePageを解放する時は、nr_hugepages ファイルに0を書き込むだけです。

1GBのHugePageを利用する場合は、書き込む場所が /sys/kernel/mm/hugepages/hugepages-1048576kB/nr_hugepages となるだけです。ただ、/proc/meminfo の表示は 2MBと1GBの両方の表示に対応していないため注意下さい。仮に2MBのHugePageを1024、1GBのHugePageを2 設定しています。

# echo 1024 > /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages
# echo 1 > /sys/kernel/mm/hugepages/hugepages-1048576kB/nr_hugepages

$ cat /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages
1024
$ cat /sys/kernel/mm/hugepages/hugepages-1048576kB/nr_hugepages
1

$ cat /proc/meminfo | grep -e Mem -e Huge
MemTotal: 8167448 kB
MemFree: 4440288 kB
MemAvailable: 4671616 kB
・・・・
HugePages_Total: 1024
HugePages_Free: 1024
HugePages_Rsvd: 0
HugePages_Surp: 0
Hugepagesize: 2048 kB
・・・・

※ # はroot権限で実行、$ は一般権限で実行

/proc/meminfoではHugePagesでは2KBの1024ページ分しか表示されませんでした。ただしnr_hugepagesの設定状況や空(HugePages_Free)容量は合計3GB減っていることからも、1GBのHugePageも確保されていることが分かります。簡易的な確認であれば/proc/meminfoを使い、詳細を確認したければnr_hugepagesを確認することをお勧めします。

DPDKアプリケーションでのメモリの指定方法

DPDKアプリケーションを起動すると、通常は割り当てたHugepageはすべて利用するイメージになります。まずはHugePageの設定 DPDKとは? ~DPDK入門 第1回~ の「DPDKの環境準備」で設定した状態を確認します。その時はDPDKの設定ツール上ではHugePage数を128で設定していました。

$ cat /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages
128
$ cat /sys/kernel/mm/hugepages/hugepages-2048kB/free_hugepages
128
$ cat /sys/kernel/mm/hugepages/hugepages-1048576kB/nr_hugepages
0
$ cat /sys/kernel/mm/hugepages/hugepages-1048576kB/free_hugepages
0

$ cat /proc/meminfo | grep -e Mem -e Huge
MemTotal: 8167448 kB
MemFree: 7533296 kB
MemAvailable: 7556924 kB
・・・・
HugePages_Total: 128
HugePages_Free: 128
HugePages_Rsvd: 0
HugePages_Surp: 0
Hugepagesize: 2048 kB
・・・・

設定通り2KBのHugePageが128ページ確保されていることが確認できました。DPDKのパケット処理 ~DPDK入門 第2回~ で紹介した L2 Forwarding Sample を動かしてみます。DPDKの設定は一通り行った上で、l2fwdを動かします。

$ sudo ./l2fwd -c 0x3 -- -p 0x3

l2fwdを実行中に再度メモリ状況を確認してみます。

$ cat /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages
128
$ cat /sys/kernel/mm/hugepages/hugepages-2048kB/free_hugepages
0
$ cat /sys/kernel/mm/hugepages/hugepages-1048576kB/nr_hugepages
0
$ cat /sys/kernel/mm/hugepages/hugepages-1048576kB/free_hugepages
0

$ cat /proc/meminfo | grep -e Mem -e Huge
MemTotal: 8167448 kB
MemFree: 7485576 kB
MemAvailable: 7548548 kB
・・・・
HugePages_Total: 128
HugePages_Free: 0
HugePages_Rsvd: 0
HugePages_Surp: 0
Hugepagesize: 2048 kB
・・・・

128ページが全てl2fwdで利用されたことが確認できました。基本的にはこの使い方で問題はないのですが、HugePageをDPDKアプリケーション以外でも利用したい、あるいはDPDKアプリケーションで利用するメモリ量を静的に設定したい、などの要望もあると思います。その場合はsocket-memオプションを利用します。

$ sudo ./l2fwd -c 0x3 --socket-mem 64 -- -p 0x3

DPDKアプリケーションが使用するHugePageを64MBに指定することができます。その時のメモリ状況は以下です。

$ cat /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages
128
$ cat /sys/kernel/mm/hugepages/hugepages-2048kB/free_hugepages
96
$ cat /sys/kernel/mm/hugepages/hugepages-1048576kB/nr_hugepages
0
$ cat /sys/kernel/mm/hugepages/hugepages-1048576kB/free_hugepages
0

$ cat /proc/meminfo | grep -e Mem -e Huge
MemTotal: 8167448 kB
MemFree: 7481000 kB
MemAvailable: 7544064 kB
・・・・
HugePages_Total: 128
HugePages_Free: 96
HugePages_Rsvd: 0
HugePages_Surp: 0
Hugepagesize: 2048 kB


想定通り64MB分のHugePage32ページが利用され、残りのページがfreeであることが確認できます。

おわりに

今回はメモリ管理の機能を説明させて頂きました。仮想メモリなどの知識は知らずともDPDKを利用することはできますが、性能をチューニングする際のノウハウとして役立ててもらえると嬉しいです。今回のブログから、図のイメージ作成などを共にDPDK関連の業務に携わっている松野 能久さんに手伝ってもらいました。

次回ですが、今回記載できなかったメモリの話をもう少しさせて頂きたいと考えています。よろしくお願いします。ご覧頂きありがとうございました。

連載シリーズ
DPDK入門
著者プロフィール
寺尾 智之
寺尾 智之
長年NTTの通信基盤となるネットワーク関連の仕事に従事。 最近では仮想化技術が主流化しており、最新動向を追従する日々。 DPDKに関してはニッチな領域のためか仲間が増えないと感じており、ブログを通した仲間づくりを開始。 横浜生まれだが、巨人ファン。たまに東京ドームに観戦に行くことが楽しみ。