web-dev-qa-db-ja.com

ldを金に置き換える-経験はありますか?

誰かがgoldの代わりに ld を使用しようとしましたか?

goldpromisesldよりもはるかに高速であるため、大規模なC++アプリケーションのテストサイクルを高速化するのに役立つ可能性がありますが、 ld?

gcc/g++gold。?を直接呼び出しますか?

既知のバグや問題はありますか?

goldはしばらくの間GNU binutilsの一部ですが、Webで「成功談」や「ハウツー」さえほとんど見つけていません。

更新:金とそれを説明するブログエントリへのリンクを追加しました

77
IanH

現時点では、Ubuntu 10.04でより大きなプロジェクトをコンパイルしています。ここでbinutils-goldパッケージと簡単にインストールして統合できます(そのパッケージを削除すると、古いldが取得されます)。 Gccは自動的にゴールドを使用します。

いくつかの経験:

  • ゴールドは/usr/local/libで検索しません
  • goldは、pthreadやrtのようなライブラリを想定しておらず、手動で追加する必要がありました
  • それはより速く、より少ないメモリを必要とします(後者は多くのブーストなどの大きなC++プロジェクトで重要です)

動作しないもの:カーネルをコンパイルできないため、カーネルモジュールがありません。 Ubuntuは、fglrxなどの専用ドライバーを更新する場合、DKMSを介してこれを自動的に行います。これはld-goldで失敗します(ゴールドを削除し、DKMSを再起動し、ld-goldを再インストールする必要があります。

49
nob

ゴールドを選択的に使用する方法(つまり、システム全体ではなくシンボリックリンクを使用する方法)を見つけるのに少し時間がかかったので、ここで解決策を投稿します。 http://code.google.com/p/chromium/wiki/LinuxFasterBuilds#Linking_using_gold に基づいています。

  1. 金のりスクリプトを配置できるディレクトリを作成します。 ~/bin/gold/を使用しています。
  2. 次のグルースクリプトをそこに入れて、~/bin/gold/ldという名前を付けます。

    #!/bin/bash
    gold "$@"
    

    明らかに、chmod a+x ~/bin/gold/ldを実行可能にします。

  3. gccへの呼び出しをgcc -B$HOME/bin/goldに変更します。これにより、gccはldなどのヘルパープログラムの特定のディレクトリを検索し、システムのデフォルトldの代わりにグルースクリプトを使用します。

38
Tilman Vogel

Gcc/g ++は直接goldを呼び出すことができますか?

答えを補足するために、gccのオプション-Fuse-ld=goldgcc doc を参照)。ただし、ビルド中にオプションが無効になるようにgccを構成することはできます。

12
user2273896

Samba開発者として、私は数年前からほぼ完全にUbuntu、Debian、およびFedoraでゴールドリンカーを使用しています。私の評価:

  • 金は、従来のリンカーよりも何倍も高速です(5〜10倍)。
  • 最初は、いくつかの問題がありましたが、おおよそUbuntu 12.04以降に問題が発生しています。
  • ゴールドリンカーは、コードにいくつかの依存関係の問題を発見しました。これは、一部の詳細に関しては従来の問題よりも正しいように見えるためです。たとえば、 このSambaコミット

金を選択的に使用したことはありませんが、ディストリビューションで提供されている場合は、シンボリックリンクまたは代替メカニズムを使用しています。

9
Michael Adam

ldgoldにリンクできます(上書きを避けるためにldがインストールされている場合は、ローカルバイナリディレクトリ内):

ln -s `which gold` ~/bin/ld

または

ln -s `which gold` /usr/local/bin/ld
8
Delan Azabani

Ldとgoldの間に互換性のない違いがあるため、一部のプロジェクトはgoldと互換性がないようです。例:OpenFOAM、 http://www.openfoam.org/mantisbt/view.php?id=685 を参照してください。

3
Kenneth Hoste

最小合成ベンチマーク

結果:金は、私が試したすべての値で約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' '{}'"

GitHubアップストリーム

タイプの入力が与えられた場合:

./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_isn_ints_per_file extern intsを追加します。

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ファイルでは、両方のメソッドでmallocが失敗することがあります
  • GCCは1Mの追加で関数をコンパイルできません

Ubuntu 18.10、GCC 8.2.0、Lenovo ThinkPad P51ラップトップ、Intel Core i7-7820HQ CPU(4コア/ 8スレッド)、Samsung M471A2K43BB1-CRC RAM(2x 16GiB)、Samsungでテスト済みMZVLB512HAJQ-000L7 SSD(3,000 MB /秒)。

また、gem5のデバッグビルドで2xを確認しました: https://gem5.googlesource.com/public/gem5/+/fafe4e80b76e93e3d0d05797904c19928587f5b5

DragonFlyBSDは、デフォルトのリンカーとしてゴールドに切り替えました。そのため、さまざまなツールの準備ができているようです。
詳細: http://phoronix.com/scan.php?page=news_item&px=DragonFlyBSD-Gold-Linker

2
usr1234567