Linux上にC++アプリがあり、レイテンシーに非常に敏感です。私のメモリ使用量は約2GBなので、4kbのページと64のTLBエントリがあると、TLBミスが発生します。
Intel開発者マニュアルを読んだところ、2MB(または4MB?)の「巨大な」ページはTLBエントリの数を半分に減らすだけなので、メモリ範囲の増加はTLBエントリの減少を相殺し、パフォーマンスが向上します。
C++アプリケーションで「巨大な」ページを使用してメモリを割り当てるにはどうすればよいですか?注意すべきトレードオフはありますか?
私のLinuxはRedHatディストリビューションです。
C++で記述された特定のアプリケーションにのみ巨大なページが必要であると想定しています。それ以外の場合は、システムのページサイズを変更するだけです。以下の方法は、任意の言語で記述されたアプリケーションで正常に機能します。
特定のアプリケーションに巨大なページを使用するには、巨大なページのサポートをサポートするカーネルを構築する必要があります。 CONFIG_HUGETLBFS
オプションを使用してカーネルを構築する必要があります
指定してページサイズを指定します
hugepagesz=<size>
ブートコマンドライン
ブートパラメータの設定方法を確認するには: http://www.cyberciti.biz/tips/10-boot-time-parameters-you-should-know-about-the-linux-kernel.html
巨大なページの数を設定するには、
# echo 20 > /proc/sys/vm/nr_hugepages
巨大なページをチェックするには(利用可能、合計、…)
# cat /proc/meminfo
上記のすべてがうまくいったら、「特定のアプリケーションでこれらのページを使用する方法」を操作する必要があります。タイプhugetlbfs
のファイルシステムをマウントします。
# mount -t hugetlbfs -o uid=<value>,gid=<value>,mode=<value>,pagesize=<value>,size=<value>,min_size=<value>,nr_inodes=<value> none /mnt/huge
アプリケーションをこのマウント/mnt/huge
ブームに配置すると、アプリケーションはユーザーが設定したページサイズを使用するようになります。
詳細については、チェックしてください https://www.kernel.org/doc/Documentation/vm/hugetlbpage.txt
巨大なページの長所/短所:
メリット:TLBミスの削減、ページフォールトの削減、ページテーブルサイズの削減、翻訳の削減による効率
デメリット:内部フラグメンテーションの増加:メモリの損失、スワッピングの待ち時間の増加(HUGETLBFS
ページはマッピングをスワップアウトしません)詳細を確認してください https://lwn.net/Articles/359158/
[〜#〜] edit [〜#〜]巨大なページを割り当てるために利用できるAPIもありますplzチェックはおそらくそれが役立ちます
https://github.com/libhugetlbfs/libhugetlbfs/blob/master/HOWTO
カーネルからの "hugetlb"ドキュメント がここで役立つはずです。
ユーザーは、mmapシステムコールまたは標準のSYSV共有メモリシステムコール(shmget、shmat)を使用して、Linuxカーネルの巨大ページサポートを使用できます。
そして:
例
1)map_hugetlb:tools/tests/selftests/vm /map_hugetlb.cを参照してください
2)hugepage-shm:tools/tests/selftests/vm /hugepage-shm.cを参照してください
3)hugepage-mmap:tools/tests/selftests/vm /hugepage-mmap.cを参照してください
4)libhugetlbfs( https://github.com/libhugetlbfs/libhugetlbfs )ライブラリは、巨大なページの使いやすさ、環境のセットアップ、および制御を支援するための幅広いユーザースペースツールを提供します。
(これらのパスはLinuxソースツリーを参照します)。
つまり、基本的には次のようになります。
mmap
をMAP_HUGETLB
フラグとともに使用します透過的な巨大ページのサポート を使用することもできます。これは、過去数年間の任意のカーネルで利用できます(少なくとも、3.xおよび4.xの範囲のすべて、およびさまざまな2.6.xカーネル) 。
主な利点は、特別な「hugetlbfs」を設定する必要がなく、「正常に機能する」ことです。欠点は、それが保証されていることです。カーネルmayは、巨大なページifが満たされ、いくつかの条件が利用可能である場合、割り当てを満たします。 。起動時に固定数の巨大なページを予約するhugetlbfs
とは異なり、特定の呼び出しを介してのみ利用可能ですが、透過的な巨大なページは、一般的なメモリプールから巨大なページを切り分けます。これには、物理メモリの連続した2MBブロックが必要ですが、物理メモリの断片化により、時間の経過とともにまれになる可能性があります。
さらに、巨大なページを取得するかどうかに影響を与えるさまざまなカーネル調整可能ファイルがありますが、その中で最も重要なのは_/sys/kernel/mm/transparent_hugepage/enabled
_です。
最善の策は、2MBの境界に_posix_memalign
_でブロックを割り当ててから、割り当てられた領域でmadvise(MADV_HUGEPAGE)
を実行することです。 before初めて触れる前。また、_aligned_alloc
_などのバリアントでも機能します。私の経験では、_/sys/kernel/mm/transparent_hugepage/enabled
_がalways
に設定されているシステムでは、これは一般に巨大なページになります。ただし、私は主に、かなりの空きメモリがあり、稼働時間が長すぎないシステムで使用しました。
2GBのメモリを使用している場合は、巨大なページから大きなメリットを得ることができます。それをすべて小さなブロックに割り当てる場合、たとえばmalloc
を介して、透過的な巨大ページが起動しない可能性が高いため、メモリの大部分を使用しているもの(多くの場合、単一のオブジェクトタイプ)をTHP対応の方法で割り当てることを検討することもできます。
また、 ライブラリ を記述して、任意の割り当てから実際にhugepagesを取得したかどうかを判断します。これはおそらく実稼働アプリケーションでは役に立ちませんが、少なくともTHPを入手したかどうかを判断できるため、THPを使おうとするルートに行く場合に役立つ診断になる可能性があります。