C++/버그 리포트(Bug report)

[BUG] Apple Clang std::hardware_xxx_interference_size

kim선달 2021. 8. 12. 01:05
Select Language

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