Link-Time Optimization(LTO; 링크타임 최적화)을 사용하지 않는 이유가 있습니까?
GCC, MSVC, LLVM 및 기타 툴체인은 컴파일 유닛 간의 콜 최적화를 가능하게 하는 링크 타임(전체 프로그램) 최적화를 지원합니다.
프로덕션 소프트웨어를 컴파일할 때 이 옵션을 활성화하지 않는 이유가 있습니까?
「실가동 소프트웨어」라고 하는 것은, 고객에게 출하하는 소프트웨어를 의미하거나, 실제 가동에 들어가는 것을 의미합니다."왜 항상 컴파일러 최적화를 사용하지 않는가?"의 답변입니다.(Mankarse가 지적한) 대부분은 코드를 디버깅하고 싶은 상황에 적용됩니다(따라서 소프트웨어는 아직 개발 단계이지 실제 가동 단계는 아닙니다).
이 답변을 쓴 지 6년이 지났기 때문에 갱신이 필요합니다.2014년에는 다음과 같은 문제가 있었습니다.
- 링크 시간 최적화로 인해 미묘한 오류가 발생할 수 있습니다.예를 들어 커널에 대한 링크 시간 최적화 등을 참조하십시오.2020년 현재로선 이 문제가 덜하다고 생각합니다.다음과 같은 종류의 컴파일러 및 링커 버그로부터 보호합니다.출하 예정인 소프트웨어가 올바른지 확인하기 위한 적절한 테스트를 실시합니다.
- 컴파일 시간 증가.예를 들어 슬림한 물체 덕분에 2014년 이후 상황이 크게 개선되었다는 주장이 있다.
- 대용량 메모리 사용이 게시물은 칸막이 덕분에 최근 몇 년간 상황이 크게 개선되었다고 주장한다.
2020년부터는 어떤 프로젝트에서도 디폴트로 LTO를 사용하려고 합니다.
이 최근의 질문은 LTO가 바람직하지 않은 영향을 미칠 수 있는 또 다른 가능성을 제기하고 있습니다.문제의 코드가 타이밍을 위해 계측되고 별도의 컴파일 유닛이 계측된 스테이트먼트와 계측 스테이트먼트의 상대적인 순서를 유지하기 위해 사용되고 있는 경우, LTO는 n을 파괴할 가능성이 높습니다.순서 순서 순서
나는 그것이 구체적이라고 말했다.
코드가 잘 작성되어 있는 경우만 유리합니다.컴파일러/링커 버그가 발생할 수 있지만 이는 모든 유형의 최적화에 해당되며 드문 경우입니다.
가장 큰 단점은 링크 시간이 대폭 늘어난다는 것입니다.
이것 말고도
임베디드 시스템의 전형적인 예를 생각해 봅시다.
void function1(void) { /*Do something*/} //located at address 0x1000
void function2(void) { /*Do something*/} //located at address 0x1100
void function3(void) { /*Do something*/} //located at address 0x1200
사전 정의된 주소 지정 함수를 사용하면 아래처럼 상대 주소를 통해 호출할 수 있습니다.
(*0x1000)(); //expected to call function2
(*0x1100)(); //expected to call function2
(*0x1200)(); //expected to call function3
LOT는 예기치 않은 동작을 일으킬 수 있습니다.
코드가 올바르게 실장되어 있는 경우, 링크 시간의 최적화는 기능에 영향을 주지 않습니다.단, 일반적으로 링크 시간 최적화가 없으면 100% 올바른 코드가 동작하지 않지만 링크 시간 최적화를 사용하면 잘못된 코드가 동작하지 않게 되는 시나리오가 있습니다.예를 들어 gcc를 사용하여 -O2에서 -O3로 최적화가 높은 수준으로 전환되는 경우에도 같은 상황이 발생합니다.
즉, 특정 컨텍스트(코드 베이스의 경과시간, 코드 베이스의 크기, 테스트의 깊이 등)에 따라서는, 이러한 변경의 리스크를 판단할 필요가 있습니다.
링크 시간 최적화에 의해 잘못된 코드로 예기치 않은 동작이 발생할 수 있는 시나리오는 다음과 같습니다.
두 개의 소스 파일이 있다고 가정합니다.read.c
그리고.client.c
이 파일을 개별 객체 파일로 컴파일합니다.파일 내read.c
함수가 있다read
특정 메모리 주소에서 읽는 것 이외에는 아무것도 할 수 없습니다.단, 이 주소의 내용은 다음과 같이 표시됩니다.volatile
하지만 안타깝게도 그것은 잊혀졌다.부터client.c
함수read
같은 함수에서 여러 번 호출됩니다.부터read
주소에서1개의 읽기만 실행되며, 의 경계를 넘어서는 최적화는 이루어지지 않습니다.read
기능.read
는 호출 시 항상 해당 메모리 위치에 액세스합니다.그 결과, 매번read
에서 호출됩니다.client.c
, 의 코드client.c
주소에서 새로 읽은 값을 얻습니다.volatile
사용되었습니다.
링크 타임 최적화를 사용하면 작은 함수는read
부터read.c
어디서 부르든 인라인으로 표시되기 쉽다.client.c
행방불명 때문에volatile
이제 컴파일러는 코드가 같은 주소에서 여러 번 읽힌다는 것을 깨닫고 메모리 액세스를 최적화할 수 있습니다.그 결과, 코드는 다른 동작을 개시합니다.
모든 구현이 모든 작업을 수행하는 데 필요한 의미론을 지원하도록 의무화하는 대신, 이 기준서는 다양한 작업에 적합하도록 의도된 구현이 C 표준이 요구하는 의미론을 넘어서는 코너 케이스의 의미론을 그러한 작업에 유용한 방식으로 정의함으로써 언어를 확장할 수 있도록 허용한다.
이 형식의 매우 일반적인 확장은 C 표준이 이러한 처리를 필요로 하는지 여부에 관계없이 크로스 모듈 함수 호출이 플랫폼의 애플리케이션 바이너리 인터페이스와 일치하는 방식으로 처리되도록 지정하는 것입니다.
따라서 다음과 같은 함수에 대해 크로스 모듈콜을 발신하는 경우
uint32_t read_uint32_bits(void *p)
{
return *(uint32_t*)p;
}
생성된 코드는 주소의 스토리지 32비트 청크에서 비트 패턴을 읽습니다.p
라고 해석합니다.uint32_t
이 값은 플랫폼의 기본 32비트 정수 형식을 사용하는데, 스토리지 청크가 어떻게 해당 비트 패턴을 보유하게 되었는지는 고려하지 않습니다.마찬가지로 컴파일러에 다음과 같은 정보가 제공되었을 경우:
uint32_t read_uint32_bits(void *p);
uint32_t f1bits, f2bits;
void test(void)
{
float f;
f = 1.0f;
f1bits = read_uint32_bits(&f);
f = 2.0f;
f2bits = read_uint32_bits(&f);
}
컴파일러는 다음을 위해 스토리지를 예약합니다.f
1.0f용 비트 패턴을 해당 스토리지에 저장합니다.read_uint32_bits
반환된 값을 저장하고 2.0f용 비트 패턴을 해당 저장소에 저장합니다.read_uint32_bits
반환된 값을 저장합니다.
표준에서는 호출된 함수가 유형을 사용하여 수신하는 주소의 스토리지를 읽을 수 있음을 나타내는 구문을 제공하지 않습니다.uint32_t
함수가 주어진 포인터가 type을 사용하여 작성되었음을 나타내는 것도 아닙니다.float
저수준 프로그래밍을 위한 구현은 이미 특별한 구문을 사용하지 않고 이러한 의미론을 지원하도록 언어를 확장했기 때문입니다.
유감스럽게도 Link Time Optimization에 추가하면 해당 일반적인 내선번호에 의존하는 모든 코드가 해제됩니다.일부 사람들은 그러한 코드가 깨졌다고 볼 수 있지만, "프로그래머가 해야 할 일을 하는 것을 막지 말라"는 C의 정신을 인식한다면, 이 기준서가 합리적인 대안을 제시하지 못한다면, 일반적인 확장에 대한 지원을 의무화하지 않는 것은 이 기준서의 사용을 폐지하려는 의도로 볼 수 없다.
LTO는 코드 서명 알고리즘의 에지 케이스 버그를 나타낼 수도 있습니다.일부 객체 또는 모듈의 TEXT 부분에 대한 특정 예상을 바탕으로 코드 서명 알고리즘을 검토합니다.이제 LTO는 TEXT 부분을 최적화하거나 코드 서명 알고리즘이 처리하도록 설계되지 않은 방식으로 여기에 내용을 삽입합니다.최악의 경우, 각 파이프라인에서 사용된 암호화 알고리즘이 미묘하게 다르기 때문에 특정 배포 파이프라인에만 영향을 미칩니다.B가 아닌 A 파이프라인에서 앱을 배포할 때 앱이 실행되지 않는 이유를 알아보세요.
LTO 지원은 버그가 심하고 LTO 관련 문제는 컴파일러 개발자에게 우선순위가 가장 낮습니다.예를 들어 다음과 같습니다.mingw-w64-x86_64-gcc-10.2.0-5
lto에서는 정상적으로 동작합니다.mingw-w64-x86_64-gcc-10.2.0-6
가 작동을멈춘 을 방금 했습니다.Windows CI windows windows windows windows windows windows windows windows windows windows windows windows windows 。
아래의 문제를 예로 들어주세요.
언급URL : https://stackoverflow.com/questions/23736507/is-there-a-reason-why-not-to-use-link-time-optimization-lto
'programing' 카테고리의 다른 글
함수의 함수 포인터 및 주소 (0) | 2022.08.19 |
---|---|
템플릿에서 직접 vuex 상태 사용/수정 (0) | 2022.08.19 |
다른 VUEj 내부에 컨테이너를 렌더링 (0) | 2022.08.19 |
Ag 그리드에서 열을 숨기는 방법 (0) | 2022.08.19 |
1 ~ 10의 Java 난수 생성 (0) | 2022.08.19 |