libhugetlbfsを使ってみる。

最近、比較的大きなデータを大量に処理するプログラムを扱っているのですが、少しでも実行時間を短縮しようと思い、libhugetlbfsを使ってみました。以下は参考にしたページです。

また、実行環境は以下の通りです。

  • linux 2.6.27
  • gcc 4.3.2
  • libhugetlbfs 2.2

パッケージはubuntu 8.10 amd64版にはないようだったので、諦めてsourceからmakeします。

私が入れてないだけなのか、ubuntuamd64版にないのか、単純にmakeすると32bit版をコンパイルしようとして失敗してしまいます。

make
	 CC32 obj32/elflink.o
In file included from /usr/include/features.h:354,
                 from /usr/include/stdio.h:28,
                 from elflink.c:23:
/usr/include/gnu/stubs.h:7:27: error: gnu/stubs-32.h: No such file or directory
make: *** [obj32/elflink.o] エラー 1

なので、明示的に64bit版を作成するように変数指定してmakeします。

make BUILDTYPE=NATIVEONLY
make install PREFIX=$HOME/opt BUILDTYPE=NATIVEONLY

特に問題なくコンパイルできました。

次にhugetlbのOS側設定を行います。

まずはcpuinfoでhugetlbのサイズを確認しておきます。
meminfoを見ると1ページは2MBでした。
(本当は確認するまでもなく、x86系は2Mと決まっているのですが…)

cat /proc/meminfo
…略…
HugePages_Total:     0
HugePages_Free:      0
HugePages_Rsvd:      0
HugePages_Surp:      0
Hugepagesize:     2048 kB
DirectMap4k:     65408 kB
DirectMap2M:   5961728 kB

今回は4GBをhugetlbとして使いたいので、1500ページ使えるように/etc/rc.localへ追記します。

/bin/echo 1500 > /proc/sys/vm/nr_hugepages
mount -t hugetlbfs -o mode=0777 none /mnt/hugetlbfs

リブート後1500ページ取れた事を確認します。

…略…
HugePages_Total:  1500
HugePages_Free:   1500
HugePages_Rsvd:      0
HugePages_Surp:      0
Hugepagesize:     2048 kB
DirectMap4k:    202624 kB
DirectMap2M:   5824512 kB

プログラムを実行する場合には、いくつかの変数設定を行って使います。

LD_PRELOAD=$HOME/opt/lib64/libhugetlbfs.so HUGETLB_MORECORE=yes ./a.out

mallocだけでなくC++のnewでもhugetlbからメモリを取得するようになるようです。

で、効果のほどはというと、memcpyをやったりするくらいだと特に変化はなく、アーキテクチャを考慮した最適化をしないとやはりダメなのかもしれません。