LDを金に置き換える - 何か経験はありますか?
-
28-09-2019 - |
解決
現時点では、Ubuntu 10.04でより大きなプロジェクトを編集しています。ここでは、それを簡単にインストールして統合できます binutils-gold
パッケージ(そのパッケージを削除すると、古いものを手に入れます ld
)。 GCCは自動的に金を使用します。
いくつかの経験:
- ゴールドは検索しません
/usr/local/lib
- 金はPthreadやRTのようなLibsを手に追加する必要がありません
- それはより速く、より少ないメモリが必要です(後のメモリは、多くのブーストなどを伴う大きなC ++プロジェクトで重要です)
機能しないもの:カーネルのものをコンパイルすることはできないため、カーネルモジュールはコンパイルできません。 Ubuntuは、FGLRXのような独自のドライバーを更新する場合、DKMSを介して自動的にこれを行います。これは失敗します ld-gold
(金を削除し、DKMSを再起動し、再インストールする必要があります ld-gold
.
他のヒント
Goldを選択的に使用する方法を見つけるのに少し時間がかかったので(つまり、Symlinkを使用してシステム全体ではありません)、ここにソリューションを投稿します。それはに基づいています http://code.google.com/p/chromium/wiki/linuxfasterbuilds#linking_using_gold .
- ゴールドグルースクリプトを配置できるディレクトリを作成します。使ってます
~/bin/gold/
. そこに次の接着剤スクリプトを入れて名前を付けます
~/bin/gold/ld
:#!/bin/bash gold "$@"
明らかに、実行可能にしてください、
chmod a+x ~/bin/gold/ld
.通話を変更します
gcc
にgcc -B$HOME/bin/gold
これは、GCCが指定されたディレクトリで、ヘルパープログラムのように見えるようにします。ld
したがって、システムデフォルトの代わりに接着スクリプトを使用しますld
.
GCC/G ++は金を直接呼び出すことができますか?
答えを補完するために:GCCのオプションがあります -fuse-ld=gold
(見る GCC Doc)。ただし、AFAIKは、オプションに効果がないようにビルド中にGCCを構成することができます。
Samba開発者として、私は数年以来、Ubuntu、Debian、およびFedoraでほぼ独占的にゴールドリンカーを使用しています。私の評価:
- 金は、古典的なリンカーよりも速い(5〜10回)何度も(フェルト:5〜10回)。
- 当初、いくつかの問題がありましたが、約Ubuntu 12.04以来なくなっています。
- ゴールドリンカーは、いくつかの詳細に関して古典的なものよりも正しいと思われるため、コードにいくつかの依存関係の問題を発見しました。参照してください このサンバコミット.
私は選択的に金を使用していませんが、分布がそれを提供している場合、Symlinksまたは代替メカニズムを使用しています。
リンクできます ld
に gold
(あなたが持っている場合、ローカルバイナリディレクトリで ld
上書きを避けるためにインストール):
ln -s `which gold` ~/bin/ld
また
ln -s `which gold` /usr/local/bin/ld
最小限の合成ベンチマーク
結果:私が試したすべての値で金は約2倍から3倍高くなりました。
生成 - オブジェクト
#!/usr/bin/env bash
set -eu
# CLI args.
# Each of those files contains n_ints_per_file ints.
n_int_file_is="${1:-10}"
n_ints_per_file="${2:-10}"
# Each function adds all ints from all files.
# This leads to n_int_file_is x n_ints_per_file x n_funcs relocations.
n_funcs="${3:-10}"
# Do a debug build, since it is for debug builds that link time matters the most,
# as the user will be recompiling often.
cflags='-ggdb3 -O0 -std=c99 -Wall -Wextra -pedantic'
# Cleanup previous generated files objects.
./clean
# Generate i_*.c, ints.h and int_sum.h
rm -f ints.h
echo 'return' > int_sum.h
int_file_i=0
while [ "$int_file_i" -lt "$n_int_file_is" ]; do
int_i=0
int_file="${int_file_i}.c"
rm -f "$int_file"
while [ "$int_i" -lt "$n_ints_per_file" ]; do
echo "${int_file_i} ${int_i}"
int_sym="i_${int_file_i}_${int_i}"
echo "unsigned int ${int_sym} = ${int_file_i};" >> "$int_file"
echo "extern unsigned int ${int_sym};" >> ints.h
echo "${int_sym} +" >> int_sum.h
int_i=$((int_i + 1))
done
int_file_i=$((int_file_i + 1))
done
echo '1;' >> int_sum.h
# Generate funcs.h and main.c.
rm -f funcs.h
cat <<EOF >main.c
#include "funcs.h"
int main(void) {
return
EOF
i=0
while [ "$i" -lt "$n_funcs" ]; do
func_sym="f_${i}"
echo "${func_sym}() +" >> main.c
echo "int ${func_sym}(void);" >> funcs.h
cat <<EOF >"${func_sym}.c"
#include "ints.h"
int ${func_sym}(void) {
#include "int_sum.h"
}
EOF
i=$((i + 1))
done
cat <<EOF >>main.c
1;
}
EOF
# Generate *.o
ls | grep -E '\.c$' | parallel --halt now,fail=1 -t --will-cite "gcc $cflags -c -o '{.}.o' '{}'"
タイプの入力が与えられます:
./generate-objects [n_int_file_is [n_ints_per_file [n_funcs]]]
これにより、次のメインが生成されます。
return f_0() + f_1() + ... + f_(n_funcs)()
ここで、各関数は個別に定義されています f_n.c
ファイル、追加します n_int_file_is
時代 n_ints_per_file
extern int:
int f_0() { return i_0_0 + i_0_1 + ... + i_(n_int_file_is)_(n_ints_per_file); }
これはにつながります:
n_int_file_is x n_ints_per_file x n_funcs
移転 リンク上。
それから私は比較しました:
gcc -ggdb3 -O0 -std=c99 -Wall -Wextra -pedantic -o main *.o
gcc -ggdb3 -O0 -std=c99 -Wall -Wextra -pedantic -fuse-ld=gold -o main *.o
さまざまな入力トリプレットの場合、それは次のとおりです。
10000 10 10
nogold: wall=3.70s user=2.93s system=0.75s max_mem=556356kB
gold: wall=1.43s user=1.15s system=0.28s max_mem=703060kB
1000 100 10
nogold: wall=1.23s user=1.07s system=0.16s max_mem=188152kB
gold: wall=0.60s user=0.52s system=0.07s max_mem=279108kB
100 1000 10
nogold: wall=0.96s user=0.87s system=0.08s max_mem=149636kB
gold: wall=0.53s user=0.47s system=0.05s max_mem=231596kB
10000 10 100
nogold: wall=11.63s user=10.31s system=1.25s max_mem=1411264kB
gold: wall=6.31s user=5.77s system=0.53s max_mem=2146992kB
1000 100 100
nogold: wall=7.19s user=6.56s system=0.60s max_mem=1058432kB
gold: wall=4.15s user=3.81s system=0.34s max_mem=1697796kB
100 1000 100
nogold: wall=6.15s user=5.58s system=0.57s max_mem=1031372kB
gold: wall=4.06s user=3.76s system=0.29s max_mem=1652548kB
私が軽減しようとしてきたいくつかの制限:
- 100k Cファイルで、両方の方法が時々マロックに失敗します
- GCCは、1M追加で関数をコンパイルできません
Ubuntu 18.10、GCC 8.2.0、Lenovo ThinkPad P51ラップトップ、Intel Core I7-7820HQ CPU(4コア / 8スレッド)、2x Samsung M471A2K43BB1-CRC RAM(2x 16GIB)、Samsung MZVLB512HHAJQ-L7 SD(3,000L7 SSD(3,000L7 SSD) )。
また、GEM5のデバッグビルドで2倍を観察しました。 https://gem5.googlesource.com/public/gem5/+/fafe4e80b76e93e3d05797904c19928587f5b5
一部のプロジェクトは、LDと金の間に互換性のない違いのために、金と互換性がないようです。例:OpenFoam、参照 http://www.openfoam.org/mantisbt/view.php?id=685 .
DragonFlyBSDは、デフォルトのリンカーとして金に切り替えました。したがって、さまざまなツールの準備ができているようです。
詳細:http://phoronix.com/scan.php?page=news_item&px=dragonflybsd-gold-linker