Linux / Unix / Interix」カテゴリーアーカイブ

distcc と ccache でビルド高速化

みむらです。

複数台のマシンをお持ちの方、絶対いらっしゃいますよね。
ついでに、隅っこで寝てるとかそういうパターン、絶対ありますよね。

ということで、そういうマシンをコンパイルの際に利用して、是非とも効率よくパワーを使いましょう。

ついでに、ccache を有効にして、キャッシュしましょうという、そんなお話。

追記ですが、 Mac OS X にはこれがなにやら、標準で入っているそうです。
Mac マシンを大量にお持ちの方は、是非ともやってみるといいんじゃないでしょうか!


ということで、カーネルを並列ビルドすることを例にして、使い方。 (Linux Mint 12 でテストしてます。)

 

1.distcc と ccache をインストール。

$ sudo aptitude install distcc ccache

 

2./etc/default/distcc を修正する。

$ sudo vim /etc/default/distcc

# 書き換えるのは下記3点

# 動作を許可させる
STARTDISTCC="false" -> STARTDISTCC="true"

# 接続可能ホストを設定する。
ALLOWEDNETS="127.0.0.1" -> ALLOWEDNETS="192.168.1.0/24"

# リスナとなる NIC の IP アドレスを入力
LISTENER="127.0.0.1" -> LISTENER="192.168.1.200"

 

3. distcc を起動する。

$ sudo service distcc start

 

4. (操作マシン側にて) 接続先のホストを、 DISTCC_HOSTS に設定

(例 192.168.1.200 と 192.168.1.201 が処理マシンだった場合 )

$ export DISTCC_HOSTS="localhost 192.168.1.200 192.168.1.201"

 

5.ビルド

# configure を行う場合
$ CC="ccache distcc gcc" CXX="ccache distcc g++" ./configure

# make を行う場合
#
# なおこの場合、物理コア数の2倍を同時実行数に指定すると、
# なんかいい感じらしいです。
#
# http://distcc.googlecode.com/svn/trunk/doc/web/faq.html
#
# 今回の場合は、各ノードに 4スレッドの CPU が乗っていて、
# 自分と、それ以外の2台のマシンがあると仮定。
#

$ make -j 24 CC="ccache distcc gcc" CXX="ccache distcc g++" HOSTCC="ccache distcc gcc" HOSTCXX="ccache distcc g++"

たぶん、HOSTCC と HOSTCXX の指定は、カーネルビルドの時ぐらいしかいらない気がしなくも。

ついでに、 configure で CC と CXX 指定したら、 make 時はいらなそうな。

とりあえず、自分の備忘録ってことで。メモメモ。

 

追記事項としては、

ビルド環境のコンパイラとかインクルードファイルとかは一緒にしておいた方がいいよということ。

あわせておかないと、面倒なことになるようです。

ソフト面だけ合っていれば問題なさそうなので、ハードウェア面は、プロセッサのアーキテクチャが違うとか、

そういう系を除けば大丈夫だと思います。

SELinux で restorecon してあうあう。

もう、毎回のごとく忘れるので、備忘録。

動かない –> /var/log/audit/audit.log* を見に行く。
毎度のごとく「コンテキストがちげーぜお兄さん」と書かれてる。

そのときに、 chcon で片付けてしまうのが私のひどく悪い癖w

いやね、なんかの拍子に restorecon して、
ぶっ飛ばしてしまうわけですよ。

ということで、それも含めて幅広く、いろいろ備忘録。

 

*ファイル関連。

chcon (CHange file selinux security CONtext)

ファイルとかディレクトリのコンテキストを変える。
一時的にそのファイルに対して、特定のコンテキストを割り当てる時に使うと良さそう

# chcon –t httpd_sys_content_t /home/hogehoge/public_html/ –R

 

ls –aZ

ファイル・ディレクトリに設定されているコンテキストを表示する。
・・要は Z オプションをつける。

# ls –Z
drwxr-xr-x. hogehoge hogehoge unconfined_u:object_r:httpd_user_content_t:s0 public_html

 

restorecon (RESTORE file(s) default selinux security CONtext)

ファイルとかディレクトリのコンテキストをデフォルト設定に戻す。
後述する semanage で恒久的に変更した場合は、その設定に戻る。

(chcon の変更は、restorecon で復元される際に破棄される。)

# restorecon /home/hogehoge/public_html/ –R

 

semanage (SElinux  policy MANAGEment tool)

ファイルとかディレクトリのコンテキストをはじめとする、様々な設定を恒久的に変更する。
このコマンドで変更した内容は、今後もデフォルト設定として保持される。

(ポートに関しては後述)

設定取得 ( –l を使う ) :
# semanage fcontext –l

追加 ( –a を使う ):
# semanage fcontext –a –t httpd_sys_content_t “/home/hogehoge/public_html/(/.*)?”

削除 ( –d を使う ):
# semanage fcontext –d –t httpd_sys_content_t “/home/hogehoge/public_html/(/.*)?”

反映させる ( restorecon を使う ):
# restorecon /home/hogehoge/public_html/ –RF

 

*実行権限関連。

setenforce ( modify the mode selinux is running in. )

Enforcing (制約が施行されてる状態) と Permissive (制約が施行されていない[許可されている] 状態)
の2つを一時的に切り替える。

恒久的に変更する場合は、 /etc/selinux/config の SELINUX を書き換える。

有効にする:
# setenforce 1

無効にする:
# setenforce 0

 

getenforce ( GET the current mode of selinux )

現在、制約が施行されている (Enforcing) か許可されている (Permissive) か、
そもそも動いてないか (Disable) を返す。

# getenforce
Enforcing

 

setsebool (SET SElinux BOOLean value)

ポリシーを変更して、特定の動作を許可したり不許可にしたりという設定ができる。

# setsebool –P ftp_home_dir on

 

getsebool (GET SElinux BOOLean value)

ポリシーを取得したり、全列挙したりする。

全列挙:
# getsebool –a

特定の要素を取得:
# getsebool ftp_home_dir

 

ps –Z

プロセスのドメインを取得する。
・・・要は –Z をつける。

# ps –Z
unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 15287 pts/0 00:00:00 bash

 

*通信ポート関連

semanage (SElinux policy MANAGEment tool)

ファイル操作は先述。プロセスが使用するポートなんかもここで設定。

ポートの設定を取得:
# semanage port –l

ポートの設定を追加 ( FTP を 11111 ポートで動作可能にする )
# semanage port –a –t ftp_port_t –p tcp 11111

ポートの設定削除
# semanage port –d –t ftp_port_t –p tcp 11111

 

とりあえず、こんな感じで。であであ。

Cコード中にマシン語を埋め込んで実行する。

なんだろう、何百番煎じな気がする。もうお茶も出なくなってお湯ですよ、お湯。

フォロワーの @pasberth さんが、「JIT ってどういう仕掛けになってるの!」といっていたので、
メモリ上にバイトコードを置いて実行する方法ということでちょろっと書いたものです。

とりあえず、ピタゴラスの定理をアセンブラで書いて、
C でぺけぺけ。

ひとまず、私の作業環境である Windows での動作確認。

440411299

そいでもって、x86 なら、どのプラットフォームでもバイナリ部分は変えなくても走るよ! ってのを示すために、
Mac を立ち上げて実行。

440460787

 


ソースコードは下記のような感じです。@pasberth さん用に書いたので、Mac 向けソースになってます
Windows で動かすには、先頭の vm_protect を VirtualProtect の形式に書き換えれば動きます。

 

#include <mach/mach.h>
#include <stdio.h>

/************************************************
 とりあえず、中のデータは16進で記録してあって、

リトルエンディアンですから、
 0x01020304 は、メモリ上に 0x04,0x03,0x02,0x01 の順で格納されます。
要は逆順です。

また、命令のオーダーについては、必ずしも何バイトということはありませんが、
最長命令は 32bit アーキテクチャですんで 4 バイト ( 32 bit / 8 = 4 byte. )

見やすくするために、2バイトや1バイト命令に関しては、
0x90 (NOP) [NOP = なにもしない] を挿入して、アライメント(区切り)を合わせてあります。

まー、適当に見てもらえれば。

************************************************/

int main(){
	unsigned long d;
	int a = 0,b = 0,c = 0;
	unsigned long code[32] = {0};
	
	printf("vm_protect : %s\n\n",vm_protect(
		mach_task_self(),
		(vm_address_t)code,32 * sizeof(long),
		FALSE,
			VM_PROT_READ | 
			VM_PROT_WRITE | 
			VM_PROT_EXECUTE
		) == KERN_SUCCESS ? "[OK]" : "[FALSE]");

	printf("INPUT [a,b,c] : ");
	scanf("%d,%d,%d",&a,&b,&c);

	code[0]  = 0x0424448B;	// MOV EAX,DWORD PTR SS:[ESP+4]
	code[1]  = 0x08244C8B;	// MOV ECX,DWORD PTR SS:[ESP+8]
	code[2]  = 0x9090C13B;	// CMP EAX,ECX
	code[3]  = 0x9090047E;	// JLE SHORT ; EIP+4
	code[4]  = 0x9090C88B;	// MOV ECX,EAX
	code[5]  = 0x0C24548B;	// MOV EDX,DWORD PTR SS:[ESP+C]
	code[6]  = 0x9090CA3B;	// CMP ECX,EDX
	code[7]  = 0x9090147E;	// JLE SHORT ; EIP+C
	code[8]  = 0x90909056;	// PUSH ESI
	code[9]  = 0x9090F28B;	// MOV ESI,EDX
	code[10] = 0x9090D18B;	// MOV EDX,ECX
	code[11] = 0x9090CE8B;	// MOV ECX,ESI
	code[12] = 0x9090905E;	// POP ESI
	code[13] = 0x90C0AF0F;	// IMUL EAX,EAX
	code[14] = 0x90C9AF0F;	// IMUL ECX,ECX
	code[15] = 0x90D2AF0F;	// IMUL EDX,EDX
	code[16] = 0x9090C103;	// ADD EAX,ECX
	code[17] = 0x9090C22B;	// SUB EAX,EDX
	code[18] = 0x9090D8F7;	// NEG EAX
	code[19] = 0x9090C01B;	// SBB EAX,EAX
	code[20] = 0x90909040;	// INC EAX
	code[21] = 0x909090C3;	// RETN
	
	printf("\nRETURN : %s\n",
		((int(*)(int,int,int))code)(a,b,c) == 0 ? "[FALSE]" : "[OK]");
	
	return 0;
}

 

中のバイトコード部分は、ソースコード中のコメントを見てもらえれば。

本来、こういうページ領域上にバイトコードを置いて、それを呼び出そうとしても、
実行できないように設定されています。

(実行できるようになっていると、プロセスに脆弱性があったとき、悪意のあるコードを攻撃者から送信されて、実行されてしまう危険性が格段に上がる)

ですが、さすがに完全に実行できないと、Java VM をはじめとしたソフトウェアが稼働できなくなってしまうため、
OSから実行可能にフラグを書き換えるAPIが提供されています。

OS

関数

Windows VirtualProtect
MSDN : http://msdn.microsoft.com/ja-jp/library/cc430214.aspx
Mac OS X vm_protect
The GNU Mach Reference Manual :
http://www.gnu.org/software/hurd/gnumach-doc/Memory-Attributes.html
Darwin :
http://web.mit.edu/darwin/src/modules/xnu/osfmk/man/vm_protect.html
Linux mprotect
Man page of MPROTECT :
http://linuxjm.sourceforge.jp/html/LDP_man-pages/man2/mprotect.2.html

実行可能なバイトコードは、x86 プロセッサ共通なので、同じプロセッサならどれでも動きますが、
各オペレーティングシステムに合わせて、上記に挙げた関数を利用して、実行可能に設定する必要があります。

 

実際の JIT コンパイラなどでは、各プラットフォームごとのライブラリや、
APIの差異の吸収が必要になって、結構面倒なことになりますが、

今回の例はきわめて単純な例を使って、 x86 プロセッサ上なら同じコードが動くということを示すのと同時に、
Java などでは、こういう感じでたぶんコードを実行しているということで。

(mono はこれ使ってる感濃厚。 ソースコードを眺めていた感じでは。

Unix と Windows 世界の融合 プロ生勉強会 第10回@品川

しゃべってきました。

 

内容は、
Windows 環境が好きだ-! という人向けに、
UNIX も使いたいんだけどどうしようという内容。

Cygwin との比較をして、
速度が速いけどライブラリが足りないよ! なんてのも。

 

以前書いた記事としては、
GNU系ツールもばっちり使える、Windows の UNIX 互換環境を試してみる。
との連携記事ですね。はい。

あと、GnuWin32 については、
Windows で GNU Tools を使う。 GnuWin32
とかとか。

あと、プレゼン中は runas コマンドを知らないという失態をしていたので、
sudo ほしいー! とか言ってましたが、
Windows の sudo / su は runas で!
これ見てください。

・・・でも、んー・・。んー・・。su さんほしい(ぁ

 

プレゼン資料:

プレゼンの動画:



その他、動画中に上がっていた質問を2つ。

1.X で動作するアプリケーションの画像あげてよ!

image

手頃に思いついたのが xterm ということで、 xterm の画像をあげておきます。
xeye などを動かせればよかったのですが、ちょっと動かなかったので、入れ直して再実験してみます。

 

2.ハルマゲドンコマンド動かしたらどうなるの

image

起動できなくなりましたとさ。

 

そんなわけで、であであー!

しゅしゅぽっぽ sl コマンド

image

どうも。みむらです。
ls コマンドってよく間違えますよね! そう、上記の様に。

$ alias sl='ls'

まさかこんな悲しいことする人はいませんよねぇ。

やぱり、男なら、

しゅっしゅっぽっぽ。 と汽車が走らなければ!


SL コマンドの導入。

1.東大の豊田先生のウェブサイトから sl コマンドのソースをダウンロードします。

$ wget http://www.tkl.iis.u-tokyo.ac.jp/~toyoda/sl/sl.tar
$ tar xvf sl.tar

image

2.Makefile をちょっとごにょごにょ。

$ sed -i -e 's/cc/gcc/g' Makefile

image

3.Make

$ make

4.(SL したい方向け) /usr/local/bin/ に配置。

$ su
Password: (パスワード)
$ mv sl /usr/local/bin/

5.きしゃぽっぽ

$ sl

image


最後に。汽車ぽっぽ入れておくと、非常にUNIX 作業が楽しくなると思います。

と同時に、こういうプログラムでも真剣に作る開発者になりたいと、そう思います。