distcc加速內核編譯


Linux內核編譯實在是費時間的事,搞內核移植的時候總要編譯,生命有一部分就浪費在等內核編譯完成上,有心想買個HP的工作站,看了下Z840的價格,想想還是算了。distcc早就聽說過,一直沒有去試試,今天終於試了試,真是大贊啊!!下面說下如何配置,為了方便敘述,先定義幾個稱呼

  • 我直接工作的電腦稱為L
  • 用來加速編譯的電腦們稱為A、B、C(它們也被稱為compile farm)

安裝

# L電腦
sudo apt install distcc distccmon-gnome distcc-pump

# A/B/C電腦
sudo apt install distcc

配置

在L/A/B/C電腦上更改 /etc/default/distcc內容如下(注釋已經刪除)

STARTDISTCC="true"

# 下面的 /16表示前面的IP地址16位有效,即192.168.xx.xx的IP都是接受的
ALLOWEDNETS="127.0.0.1 192.168.0.0/16"

LISTENER=""

NICE="10"

JOBS=""

ZEROCONF="true"

 然后執行

sudo systemctl restart distcc

  此時,若在任何一台電腦上執行 distcc --show-hosts,將會列出L/A/B/C電腦的IP或IPv6,格式為

<A-IP>:3632/32
<C-IP>:3632/16
<B-IP>:3632/8
<L-IP>:3632/32

 其中3632是端口,這個是默認端口,一般不用改變,'/'后面限制的任務數,默認按4倍<CPU-threads>來計算的,如果這個時候執行后面將會提到的distcc-pump就會報沒有host具有,cpp屬性(這可以認為是distcc的一個bug,不過人家在man distcc里說明了,zeroconf不支持lzo和cpp屬性,github上也明確表示不會合並patch,所以zeroconf我覺得也就是可以用來debug或初始化)

L電腦的打開 /etc/distcc/hosts,將剛才 distcc --show-hosts的輸出寫進去,並在每行后面加上,cpp,lzo,大約如下(把+zeroconf注釋掉

<A-IP>:3632/32,cpp,lzo
<C-IP>:3632/16,cpp,lzo
<B-IP>:3632/8,cpp,lzo
<L-IP>:3632/32,cpp,lzo

  使用hosts文件有幾個好處(可能就是因為這些好處,以至於開發者都不去修正zeroconf的BUG)

  • 各電腦按照配置高低排序,把配置高的放前面,當任務少時先分配給配置高的機器
  • 各電腦的任務限制數可以手動更改(給A/B/C電腦一點剩余CPU)
  • L電腦自己需要執行預處理任務,應該把自己放到靠后的位置,並適當限制任務數,甚至不要放到列表中去
  • 手動增加,cpp,lzo屬性,避開BUG

配置完成后,此時在L電腦上再次執行 distcc --show-hosts,輸出就是/etc/distcc/hosts的文件內容

安裝編譯器

所有電腦需要安裝編譯器,並且放到相同的位置(我認為不太必要,只要都在PATH環境變量中就可以了吧),最好都是相同的版本。

編譯內核

編譯內核時,一般會先export ARCH 和 CROSS_COMPILE,這個不用改變,正常來即可,也可以放到命令行上,我比較喜歡export,最后編譯執行命令是

distcc-pump make -j$(distcc -j) O=build-xxx CC="distcc ${CROSS_COMPILE}gcc"

  這個時候可以打開 distccmon-gnome 看看壯觀的景象,幾分鍾之后內核就編譯好了!

后記

還有一個叫dmucs的東西,可以手動指定每台機器的power,然后自動執行負載均衡,並優先發給power強的機器,不過我配置的半天都不好使,而且我覺得配置起來也比較麻煩,就放棄了。有興趣的同志可以研究下。

補記

在編譯Linux內核某版本時,總是報遠程無法編譯過,但本地可以編譯過,然后后面就會使用plain distcc mode,也就是本地預處理,遠程編譯的方式。這種方式顯著降低編譯速度,因為大量工作由本機來完成,而我本機的性能還不如編譯服務器,一開始我也以為配置的問題,后來 man include_server告訴我,可以 export DISTCC_FALLBACK=0,然后遠程編譯的錯誤信息就會打出來,便於診斷,發現是下面的代碼的問題

#define __gcc_header(x) #x
#define _gcc_header(x) __gcc_header(linux/compiler-gcc##x.h)
#define gcc_header(x) _gcc_header(x)
#include gcc_header(__GNUC__)

 

也就是說distcc預處理時無法知道要發送哪個頭文件,並且沒有檢測出這個問題,導致遠程編譯時報 linux/compiler-gcc##x.h 未找到,這個問題work around的方法是,根據打印消息,把源代碼臨時改掉,不要因為這一個問題,導致編譯速度顯著下降。

另外 CC=distcc xxxx,如果xxxx不是絕對路徑,那在遠程編譯服務器上也會按PATH去搜索,不過要注意PATH在遠程是什么,如果是絕對路徑就不需要搜索了,直接也使用絕對路徑。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM