Ld'yi altınla değiştirmek - herhangi bir deneyim?


81

goldBunun yerine kullanmaya çalışan oldu ldmu?

gold daha hızlı olacağını vaat ediyorld , bu nedenle büyük C ++ uygulamaları için test döngülerini hızlandırmaya yardımcı olabilir, ancak ld yerine drop-in yerine kullanılabilir mi?

Can gcc/ g++doğrudan çağrı gold.?

Bilinen herhangi bir hata veya sorun var mı?

goldBir süredir GNU binutillerinin bir parçası olmasına rağmen , Web'de neredeyse hiç "başarı öyküsü" ve hatta "Howtos" bulamadım.

( Güncelleme: altına bağlantılar ve bunu açıklayan blog girişi eklendi )

Yanıtlar:


53

Şu anda Ubuntu 10.04'te daha büyük projeler derliyor. Burada binutils-goldpaketle kolayca kurabilir ve entegre edebilirsiniz (bu paketi kaldırırsanız eskisini alırsınız ld). Gcc otomatik olarak altın kullanacaktır.

Bazı deneyimler:

  • altın aramaz /usr/local/lib
  • altın, pthread veya rt gibi lib'leri kabul etmez, bunları elle eklemek zorunda kalır
  • daha hızlıdır ve daha az belleğe ihtiyaç duyar (daha sonra, çok fazla destek içeren büyük C ++ projelerinde önemlidir vb.)

Ne işe yaramaz: Çekirdek malzemelerini derleyemez ve bu nedenle çekirdek modülleri olamaz. Ubuntu, fglrx gibi tescilli sürücüleri güncellerse bunu DKMS aracılığıyla otomatik olarak yapar. Bu başarısız olur ld-gold(altını kaldırmanız, DKMS'yi yeniden başlatmanız, yeniden yüklemeniz gerekir ld-gold.


Teşekkürler, sanırım bir deneyeceğim - bahsettiğiniz kısıtlamalar benim durumumda sorun değil gibi görünüyor.
IanH

+1: deneyim paylaştığınız için teşekkürler. Peki ya performans?
nöro

9
özellikle büyük statik kitaplıkları bir ikiliye bağlarken önemli ölçüde daha hızlıdır, ancak herhangi bir zor ölçüm yapmadık.
nob

2
@neuro Ölçümlerim, birçok nesneyi ve .a dosyasını bir dizi ~ 30 .so dosyasına (biri büyük, geri kalanı küçük) ve önemli bir ticari uygulama için 1 yürütülebilir dosyaya bağlamak içindi. Yalnızca bağlantı süresini ölçerek ve seri olarak çalıştırmayı ölçerek, derleme başına 6,24 saniye iyileştirme için toplamda ld ile 22,48 saniye ve altın ile 16,24 saniye elde ettim. Bununla birlikte, 8 işlemciyle paralel olarak çalıştırırsam, toplam fark derleme başına yalnızca 1,42 saniyedir. Genel bellek kullanımı, paralelleştirme yapmadan bağımsız olarak% 42'lik bir iyileşmedir. YMMV.
metal

@metal: rakamlar için çok teşekkürler. Bellek kullanımı iyileştirmesi harika görünüyor ld, bu konuda çok hırslı.
nöro

40

Altını seçmeli olarak nasıl kullanacağımı bulmam biraz zaman aldığından (yani bir sembolik bağ kullanarak sistem genelinde değil), çözümü buraya göndereceğim. Http://code.google.com/p/chromium/wiki/LinuxFasterBuilds#Linking_using_gold'a dayanmaktadır .

  1. Altın tutkal komut dosyası koyabileceğiniz bir dizin oluşturun. Ben kullanıyorum ~/bin/gold/.
  2. Aşağıdaki tutkal komut dosyasını oraya koyun ve adlandırın ~/bin/gold/ld:

    #!/bin/bash
    gold "$@"
    

    Açıkçası, çalıştırılabilir hale getirin chmod a+x ~/bin/gold/ld.

  3. Çağrılarınızı , gcc'nin verilen dizinde yardımcı programlar gibi görünmesini sağlayacak gccşekilde değiştirin ve böylece sistem varsayılanı yerine yapıştırıcı betiğini kullanır .gcc -B$HOME/bin/goldldld


1
Bu hangi işletim sistemi için gerekli? Nobuntu için cevabında söylediği gibi, sadece altın binutils paketini kurun ve derleyici onu hemen kullanacaktır. OpenSuse için aynı.
usr1234567

8
Evet, ld'yi sistem genelinde değiştirmek oldukça kolaydır. Cevabım özellikle altının seçici olarak nasıl kullanılacağına yönelikti. Ve bu durumda, herhangi bir işletim sistemi için gerekli olduğunu düşünüyorum.
Tilman Vogel

1
@vidstige Evet, senaryonun avantajı arar olmasıdır goldüzerinde PATH. Bir sembolik bağlantı için tam yolu göstermeniz gerekir.
Tilman Vogel

18

Gcc / g ++ doğrudan altını arayabilir mi?

Sadece cevapları tamamlamak için: bir gcc seçeneği vardır -fuse-ld=gold( gcc belgesine bakın ). Yine de AFAIK, derleme sırasında gcc'yi seçeneğin herhangi bir etkisi olmayacak şekilde yapılandırmak mümkündür.


5
-fuse-ld=goldtamamlanmadı. -Wl,-fuse-ld=goldBağlantı sırasında kullanıldığı gibi kullanmanız gerekiyorsa.
Nawaz

6
@Nawaz No, -Wl,bir seçeneği doğrudan ld; başka bir bağlayıcı kullanmak için bunu söylemeniz gerekir gcc. Lütfen dokümana bakın .
calandoa

11

Bir Samba geliştiricisi olarak, birkaç yıldan beri altın bağlayıcıyı neredeyse yalnızca Ubuntu, Debian ve Fedora'da kullanıyorum. Değerlendirmem:

  • altın, klasik bağlayıcıdan birçok kez (keçe: 5-10 kat) daha hızlıdır.
  • Başlangıçta, birkaç sorun vardı, ancak kabaca Ubuntu 12.04'ten beri gitti.
  • Altın bağlayıcı, bazı ayrıntılar açısından klasik olandan daha doğru göründüğü için kodumuzda bazı bağımlılık sorunları buldu. Bakın, örneğin bu Samba işlemi .

Altını seçici olarak kullanmadım, ancak dağıtım sağlıyorsa sembolik bağları veya alternatifler mekanizmasını kullanıyorum.


9

Sen arasında bağlantı kuracak ldkadar gold(eğer varsa yerel bir ikili dizinde ldönlemek üzerine yazmaya yüklü):

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

veya

ln -s `which gold` /usr/local/bin/ld

6

Minimum sentetik kıyaslama: LD - altın - LLVM LLD

Sonuç:

  • altın , -Wl,--threads -Wl,--thread-count=$(nproc)çoklu iş parçacığını etkinleştirmek için kullanırken denediğim tüm değerler için yaklaşık 3 kat ila 4 kat daha hızlıydı
  • LLD , altından yaklaşık 2 kat daha hızlıydı!

Test edildi:

  • Ubuntu 20.04, GCC 9.3.0, binutils 2.34, sudo apt install lldLLD 10
  • Lenovo ThinkPad P51 dizüstü bilgisayar, Intel Core i7-7820HQ CPU (4 çekirdek / 8 iş parçacığı), 2x Samsung M471A2K43BB1-CRC RAM (2x 16GiB), Samsung MZVLB512HAJQ-000L7 SSD (3.000 MB / s).

Kıyaslama parametrelerinin basitleştirilmiş açıklaması:

  • 1: semboller sağlayan nesne dosyalarının sayısı
  • 2: sembol sağlayıcı nesne dosyası başına sembol sayısı
  • 3: sağlanan tüm sembol sembollerini kullanan nesne dosyalarının sayısı

Farklı karşılaştırma parametreleri için sonuçlar:

10000 10 10
nogold:  wall=4.35s user=3.45s system=0.88s 876820kB
gold:    wall=1.35s user=1.72s system=0.46s 739760kB
lld:     wall=0.73s user=1.20s system=0.24s 625208kB

1000 100 10
nogold:  wall=5.08s user=4.17s system=0.89s 924040kB
gold:    wall=1.57s user=2.18s system=0.54s 922712kB
lld:     wall=0.75s user=1.28s system=0.27s 664804kB

100 1000 10
nogold:  wall=5.53s user=4.53s system=0.95s 962440kB
gold:    wall=1.65s user=2.39s system=0.61s 987148kB
lld:     wall=0.75s user=1.30s system=0.25s 704820kB

10000 10 100
nogold:  wall=11.45s user=10.14s system=1.28s 1735224kB
gold:    wall=4.88s user=8.21s system=0.95s 2180432kB
lld:     wall=2.41s user=5.58s system=0.74s 2308672kB

1000 100 100
nogold:  wall=13.58s user=12.01s system=1.54s 1767832kB
gold:    wall=5.17s user=8.55s system=1.05s 2333432kB
lld:     wall=2.79s user=6.01s system=0.85s 2347664kB

100 1000 100
nogold:  wall=13.31s user=11.64s system=1.62s 1799664kB
gold:    wall=5.22s user=8.62s system=1.03s 2393516kB
lld:     wall=3.11s user=6.26s system=0.66s 2386392kB

Bu, bağlantı testleri için tüm nesneleri oluşturan komut dosyasıdır:

nesneler oluşturmak

#!/usr/bin/env bash
set -eu

# CLI args.

# Each of those files contains n_ints_per_file ints.
n_int_files="${1:-10}"
n_ints_per_file="${2:-10}"

# Each function adds all ints from all files.
# This leads to n_int_files 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_files" ]; 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 yukarı akış .

Her C dosyası oldukça büyük olabileceğinden, nesne dosyası oluşturmanın oldukça yavaş olabileceğini unutmayın.

Bir tür girdi verildiğinde:

./generate-objects [n_int_files [n_ints_per_file [n_funcs]]]

üretir:

main.c

#include "funcs.h"

int main(void) {
    return f_0() + f_1() + ... + f_<n_funcs>();
}

f_0.c, f_1.c, ..., f_<n_funcs>.c

extern unsigned int i_0_0;
extern unsigned int i_0_1;
...
extern unsigned int i_1_0;
extern unsigned int i_1_1;
...
extern unsigned int i_<n_int_files>_<n_ints_per_file>;

int f_0(void) {
    return
    i_0_0 +
    i_0_1 +
    ...
    i_1_0 +
    i_1_1 +
    ...
    i_<n_int_files>_<n_ints_per_file>
}

0.c, 1.c, ..., <n_int_files>.c

unsigned int i_0_0 = 0;
unsigned int i_0_1 = 0;
...
unsigned int i_0_<n_ints_per_file> = 0;

bu şunlara yol açar:

n_int_files x n_ints_per_file x n_funcs

bağlantıdaki yer değiştirmeler .

Sonra karşılaştırdım:

gcc -ggdb3 -O0 -std=c99 -Wall -Wextra -pedantic               -o main *.o
gcc -ggdb3 -O0 -std=c99 -Wall -Wextra -pedantic -fuse-ld=gold -Wl,--threads -Wl,--thread-count=`nproc` -o main *.o
gcc -ggdb3 -O0 -std=c99 -Wall -Wextra -pedantic -fuse-ld=lld  -o main *.o

Test parametrelerini seçerken azaltmaya çalıştığım bazı sınırlar:

  • 100k C dosyalarında, her iki yöntem de ara sıra başarısız malloc alır
  • GCC, 1M eklemeli bir işlevi derleyemez

Gem5'in hata ayıklama yapısında da 2x gözlemledim: https://gem5.googlesource.com/public/gem5/+/fafe4e80b76e93e3d0d05797904c19928587f5b5

Benzer soru: /unix/545699/what-is-the-gold-linker

Phoronix karşılaştırmaları

Phoronix, 2017'de bazı gerçek dünya projeleri için bazı kıyaslamalar yaptı, ancak inceledikleri projeler için altın kazanımları o kadar önemli değildi: https://www.phoronix.com/scan.php?page=article&item=lld4-linux-tests&num = 2 ( arşiv ).

Bilinen uyumsuzluklar

LLD karşılaştırmaları

At https://lld.llvm.org/ bir kaç tanınmış projeler için inşa süreleri verir. sentetik kıyaslamalarıma benzer sonuçlarla. Proje / bağlayıcı sürümleri maalesef verilmiyor. Sonuçlarında:

  • altın LD'den yaklaşık 3x / 4x daha hızlıydı
  • LLD, altından 3 kat / 4 kat daha hızlıydı, bu nedenle sentetik kıyaslamama göre daha hızlı

Yorum yapıyorlar:

Bu, SSD sürücülü 2 soketli 20 çekirdekli 40 dişli Xeon E5-2680 2,80 GHz makinede bağlantı süresi karşılaştırmasıdır. Çoklu iş parçacığı desteği olsun veya olmasın altın ve lld çalıştırdık. Multi-threading'i devre dışı bırakmak için komut satırlarına -no-thread ekledik.

ve sonuçlar şöyle görünür:

Program      | Size     | GNU ld  | gold -j1 | gold    | lld -j1 |    lld
-------------|----------|---------|----------|---------|---------|-------
  ffmpeg dbg |   92 MiB |   1.72s |   1.16s  |   1.01s |   0.60s |  0.35s
  mysqld dbg |  154 MiB |   8.50s |   2.96s  |   2.68s |   1.06s |  0.68s
   clang dbg | 1.67 GiB | 104.03s |  34.18s  |  23.49s |  14.82s |  5.28s
chromium dbg | 1.14 GiB | 209.05s |  64.70s  |  60.82s |  27.60s | 16.70s

1
Bulgularınızı doğrulayabilirim, projelerim arasında benzer bir hızlanma görüyorum. Ayrıca burada kriterler bakınız lld.llvm.org
ypnos


Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.