ld를 금으로 대체-경험이 있습니까?


81

누구든지 gold대신 사용하려고 ld했습니까?

gold 보다 훨씬 빠르기 ld때문에 대규모 C ++ 애플리케이션의 테스트주기를 가속화하는 데 도움이 될 수 있지만 ld의 드롭 인 대체물로 사용할 수 있습니까?

gcc/ g++직접 전화 gold.?

알려진 버그 나 문제점이 있습니까?

goldGNU binutils의 일부 이지만 웹에서 "성공 사례"나 "Howtos"조차 거의 발견하지 못했습니다.

( 업데이트 : 골드에 대한 링크 및이를 설명하는 블로그 항목 추가 )

답변:


53

현재 Ubuntu 10.04에서 더 큰 프로젝트를 컴파일하고 있습니다. 여기에서 binutils-gold패키지를 쉽게 설치하고 통합 할 수 있습니다 (해당 패키지를 제거하면 이전 버전을 얻게됩니다 ld). Gcc는 자동으로 금을 사용합니다.

일부 경험 :

  • 금은 검색하지 않습니다 /usr/local/lib
  • gold는 pthread 또는 rt와 같은 libs를 가정하지 않고 직접 추가해야했습니다.
  • 더 빠르고 더 적은 메모리를 필요로합니다 (나중에 많은 부스트가있는 큰 C ++ 프로젝트에서 중요합니다).

작동하지 않는 것 : 커널을 컴파일 할 수 없으므로 커널 모듈이 없습니다. Ubuntu는 fglrx와 같은 독점 드라이버를 업데이트하는 경우 DKMS를 통해이 작업을 자동으로 수행합니다. 이것은 실패합니다 ld-gold(골드를 제거하고 DKMS를 다시 시작하고 ld-gold.


감사합니다. 시도해 보겠습니다. 제 경우에는 언급하신 제한 사항이 문제가되지 않는 것 같습니다.
IanH

+1 : 경험을 공유해 주셔서 감사합니다. 성능은 어떻습니까?
neuro

9
특히 거대한 정적 라이브러리를 하나의 바이너리에 연결하는 경우 훨씬 더 빠르지 만 측정을 어렵게 만들지는 않았습니다.
nob

2
@neuro 내 측정은 많은 개체와 .a 파일을 ~ 30 개의 .so 파일 집합 (하나는 큰 파일, 나머지는 작음) 및 중요한 상용 응용 프로그램을위한 실행 파일 1 개로 연결하는 것입니다. 링크 시간 만 측정하고 연속적으로 make를 실행 한 결과, 빌드 당 6.24 초의 향상을 위해 ld의 경우 총 22.48 초, 금의 경우 16.24 초의 총 시간을 얻었습니다. 그러나 8 개의 프로세서와 함께 make를 병렬로 실행하면 총 차이는 빌드 당 1.42 초에 불과합니다. 전체 메모리 사용량은 make 병렬화에 관계없이 42 % 향상되었습니다. YMMV.
metal

@metal : 수치에 감사드립니다. 메모리 사용량 개선이 멋져 보이고 ld너무 탐욕 스럽습니다.
뉴로

40

골드를 선택적으로 사용하는 방법 (즉, 심볼릭 링크를 사용하는 시스템 전체가 아님)을 찾는 데 시간이 좀 걸렸으므로 여기에 솔루션을 게시하겠습니다. 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. 에 통화 변경 gccgcc -B$HOME/bin/gold같은 도우미 프로그램에 대해, 지정된 디렉토리에 GCC 모양을 만드는 ld때문에 대신 시스템 기본의 접착제 스크립트를 사용을 ld.


1
어떤 운영 체제에 필요한가요? nob가 대답에서 말했듯이 Ubuntu의 경우 금색 binutils-package를 설치하면 컴파일러가 즉시 사용합니다. openSuse도 마찬가지입니다.
usr1234567 2014

8
예, ld 시스템 전체를 교체하는 것은 매우 쉽습니다. 내 대답은 특히 금을 선택적으로 사용하는 방법에 맞춰져있었습니다. 그리고 그 경우 모든 OS에 필요하다고 생각합니다.
Tilman Vogel 2014

1
@vidstige 예, 스크립트의 장점은 찾는 것입니다 goldPATH. 심볼릭 링크의 경우 전체 경로를 가리켜 야합니다.
Tilman Vogel

17

gcc / g ++에서 gold를 직접 호출 할 수 있습니까?

답변을 보완하기 위해 gcc 옵션이 있습니다 -fuse-ld=gold( gcc doc 참조 ). 그러나 AFAIK는 옵션이 효과가없는 방식으로 빌드 중에 gcc를 구성 할 수 있습니다.


5
-fuse-ld=gold완전하지 않습니다. -Wl,-fuse-ld=gold링크시 사용 되는 그대로 사용해야 하는 경우.
Nawaz 2011

6
@Nawaz No, -Wl,옵션을 직접 전달하는 데 사용됩니다 ld. 다른 링커를 사용하려면 gcc. 문서를 참조하십시오 .
calandoa

11

Samba 개발자로서 저는 몇 년 동안 우분투, 데비안, 페도라에서 거의 독점적으로 골드 링커를 사용하고 있습니다. 내 평가 :

  • 금은 고전적인 링커보다 몇 배 (느낌 : 5-10 배) 빠릅니다.
  • 처음에는 몇 가지 문제가 있었지만 대략 Ubuntu 12.04 이후로 사라졌습니다.
  • 골드 링커는 일부 세부 사항과 관련하여 고전적인 것보다 더 정확 해 보이기 때문에 우리 코드에서 일부 종속성 문제를 발견했습니다. 예를 들어이 Samba commit을 참조하십시오 .

나는 금을 선택적으로 사용하지 않았지만 배포판에서 제공하는 경우 심볼릭 링크 또는 대체 메커니즘을 사용했습니다.


9

( 덮어 쓰기를 방지하기 위해 설치 한 경우 로컬 바이너리 디렉토리에) 링크 ldgold수 있습니다 ld.

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

또는

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

5

최소 합성 벤치 마크 : LD 대 금 대 LLVM LLD

결과:

  • 골드-Wl,--threads -Wl,--thread-count=$(nproc)멀티 스레딩을 활성화하기 위해 사용할 때 시도한 모든 값에 대해 약 3 배에서 4 배 더 빠릅니다.
  • LLD 는 금보다 약 2 배 더 빠릅니다!

테스트 대상 :

  • Ubuntu 20.04, GCC 9.3.0, binutils 2.34, sudo apt install lldLLD 10
  • Lenovo ThinkPad P51 노트북, Intel Core i7-7820HQ CPU (4 코어 / 8 스레드), 2x Samsung M471A2K43BB1-CRC RAM (2x 16GiB), Samsung MZVLB512HAJQ-000L7 SSD (3,000MB / s).

벤치 마크 매개 변수에 대한 간략한 설명 :

  • 1 : 기호를 제공하는 오브젝트 파일 수
  • 2 : 기호 공급자 개체 파일 당 기호 수
  • 3 : 제공된 모든 기호 기호를 사용하는 개체 파일 수

다양한 벤치 마크 매개 변수에 대한 결과 :

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

다음은 링크 테스트를위한 모든 개체를 생성하는 스크립트입니다.

객체 생성

#!/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 업스트림 .

각 C 파일이 상당히 클 수 있으므로 오브젝트 파일 생성이 상당히 느릴 수 있습니다.

입력 된 유형 :

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

다음을 생성합니다.

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;

결과 :

n_int_files 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 -Wl,--threads -Wl,--thread-count=`nproc` -o main *.o
gcc -ggdb3 -O0 -std=c99 -Wall -Wextra -pedantic -fuse-ld=lld  -o main *.o

테스트 매개 변수를 선택할 때 완화하려는 몇 가지 한계 :

  • 100k C 파일에서 두 방법 모두 때때로 실패한 malloc을 얻습니다.
  • GCC는 1M이 추가 된 함수를 컴파일 할 수 없습니다.

또한 gem5의 디버그 빌드에서 2x를 관찰했습니다 : https://gem5.googlesource.com/public/gem5/+/fafe4e80b76e93e3d0d05797904c19928587f5b5

비슷한 질문 : /unix/545699/what-is-the-gold-linker

Phoronix 벤치 마크

Phoronix는 일부 실제 프로젝트에 대해 2017 년 벤치마킹을 수행했지만 그들이 조사한 프로젝트의 경우 금상 이득이 그다지 중요하지 않았습니다 : https://www.phoronix.com/scan.php?page=article&item=lld4-linux-tests&num = 2 ( 아카이브 ).

알려진 비 호환성



당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.