Apple Clang 컴파일러 버그
1. 설명
C++17부터는 true sharing 이 일어나는 메모리의 최대 크기와, 그 반대인 false sharing이 일어나는 메모리의 최소 크기를 얻어오는 표준이 지정되었습니다.
Sharing은 보통 멀티스레드 환경에서 캐시 동기화때문에 일어나게 되는데, 보다 자세한 내용은 다른 글에서 다루도록 하겠습니다.
두 값 모두 실제 CPU의 캐시 라인과 관련이 있습니다.
하지만 실제로 이 표준을 구현하는 컴파일러는 2021년 8월 현재로써는 마이크로소프트의 컴파일러 뿐이고, 다른 계열들은 해당 표준을 구현하지 않았습니다.
대신 구현 여부를 매크로로 알아낼 수 있는데, Apple Clang에서는 해당 매크로조차 잘못 정의가되어 있는 상황입니다.
2. 예시
해당 표준이 구현되어 있는지의 여부는 아래와 같은 매크로를 통해 확인이 가능합니다
#include <new>
# ifdef __cpp_lib_hardware_interference_size
std::size_t false_sharing = std::hardware_destructive_interference_size;
std::size_t true_sharing = std::hardware_constructive_interference_size;
# endif
해당 매크로가 정의되어 있음에도 저 표준이 구현되어 있지 않은 경우에는 언어적으로 판단하는건 불가능하고, 그냥 컴파일 되는지 수동으로 확인을 해야 합니다.
아니면 컴파일을 자동화시켜 스크립트로 실패여부를 반환해 그걸 매크로 인풋으로 넣으면 언어적으로 판단이 가능은 할 것 같네요...
현재는 Apple Clang을 제외한 MSVC, GCC, Clang은 모두 해당 매크로가 잘 정의되어 있습니다.
3. 대안
매크로가 잘 정의되어 있든 아니든 일단 MSVC를 제외한 다른 컴파일러에서는 해당 표준을 사용하지 못합니다.
대신 두 값 모두 alignof(std::max_align_t) 보다 같거나 크다는것이 보장되어 있다고는 하는데, 이게 사실인지는 잘 모르겠습니다(애초에 없어서 확인이 안 되니..).
그래도 현대 CPU들은 대부분 캐시 라인이 대부분 64byte 보다 같거나 적으니 64로정의해서 사용을 하거나, 불안하면 128이나 256으로 정의해서 사용하시면 대부분의 경우에는 무방합니다.
true sharing, false sharing 이 일어나는 조건과 런타임 실행 시간을 가지고 실제 캐시 라인을 얻어오는 글은 작성하는대로 여기에 달아두겠습니다.
참고한 곳: https://en.cppreference.com/w/cpp/thread/hardware_destructive_interference_size
'C++ > 버그 리포트(Bug report)' 카테고리의 다른 글
[BUG Report] MSVC(C++20) Closure type's special member function (0) | 2021.08.11 |
---|