C++ 19

True sharing / False sharing : std::hardware_..._interference_size

True sharing / False sharing : std::hardware_..._interference_size 1. 설명 False sharing은 2개 이상의 코어가 서로 다른 메모리 주소에 접근하지만, 두 주소가 동일한 캐시 최소 단위에 적제되어 있어(논리적으로는 전혀 영향이 없지만 캐시는 이를 모르기에) 동기화가 이루어져 성능이 하락하는것을 말합니다. True sharing은 false sharing과는 반대로 동일한 메모리 주소에 값을 쓸때를 의미합니다. 이때는 당연히 동기화가 이루어지기에(논리적으로도 그것이 맞고) 이번글에서는 딱히 다루지 않겠습니다. C++17 에는 이렇게 동일한 캐시라인에 적제되는지 판별할수 있는(L1 캐시 라인 크기를 얻어오는) 표준이 추가되었습니다. 다만, 아직까..

C++/개념(Concept) 2021.08.30

[BUG] Apple Clang std::hardware_xxx_interference_size

Apple Clang 컴파일러 버그 1. 설명 C++17부터는 true sharing 이 일어나는 메모리의 최대 크기와, 그 반대인 false sharing이 일어나는 메모리의 최소 크기를 얻어오는 표준이 지정되었습니다. Sharing은 보통 멀티스레드 환경에서 캐시 동기화때문에 일어나게 되는데, 보다 자세한 내용은 다른 글에서 다루도록 하겠습니다. 두 값 모두 실제 CPU의 캐시 라인과 관련이 있습니다. 하지만 실제로 이 표준을 구현하는 컴파일러는 2021년 8월 현재로써는 마이크로소프트의 컴파일러 뿐이고, 다른 계열들은 해당 표준을 구현하지 않았습니다. 대신 구현 여부를 매크로로 알아낼 수 있는데, Apple Clang에서는 해당 매크로조차 잘못 정의가되어 있는 상황입니다. 2. 예시 해당 표준이 구..

[BUG Report] MSVC(C++20) Closure type's special member function

마이크로소프트 컴파일러 C++20 feature 버그 1. 서론 C++20 에서 Closure type 이 이제 캡처가 없는 경우 특수 멤버 함수(기본 생성, 복사/이동 연산)를 제공하게 되었습니다. 여기서, 캡처가 없다는것은 실제로 내부에선 캡처된 객체를 사용하지 않더라도, 무조건 코드상에 캡처가 표시가 되어있는가를 기준으로 판단되어집니다. Proposal cppreference expr.prim.lambda_closure 2. 예시 int x = 1; auto lambda1 = []() { return 1; }; auto lambda2 = [&]() { return x; }; auto lambda3 = [&]() { return 1; }; 위에서 말했듯이, 실제 내부적으로 캡처된것이 사용되는지의 여부..

deleted 함수와 이동 연산의 overload resolution

deleted 함수와 이동 연산의 overload resolution 1. 설명 특수 멤버 함수는 경우에 따라 암시적으로 자동생성되지 않을 수도 있고, 혹은 명시적으로 삭제할수도 있습니다. 이러한 두 경우에 따라서 이동 연산(이동 생성, 이동 대입)이 overload 에 참여할 수도, 참여하지 않을 수도 있습니다. 그러면 경우에 따라 이동을 의도했지만 실제로는 복사가 일어나게 될 수 있으며, 성능 저하(대게는 프로그래머가 의도하지 않은)가 일어날 수 있습니다. 본 글에서는 편의를 위해 암시적으로 자동생성되지 않은 경우를 암시적 삭제로 부르도록 하겠습니다. 2. 예시 우선, 객체가 trivial 한 복사 및 이동연산을 지원한다면, 이동 연산은 무조건 복사 연산으로 대체됩니다. 사실 당연한 것입니다. tri..

C++/개념(Concept) 2021.05.30

C++ 개념: 특수 멤버 함수(special member function)

특수 멤버 함수(Special Member Function) 1. 설명 클래스의 다음과 같은 멤버 함수들을 말합니다. 1. 기본 생성자(constructo) 2. 소멸자(destructor) 3. 복사 생성자 및 복사 할당(assignment)자 4. 이동 생성자 및 이동 할당자 소멸자는 명시적(explicitly)으로 삭제하지 않는 한, 무조건 생성됩니다. 소멸자를 제외한 5가지 항목은, 사용자가 명시적으로 삭제하지 않아도 암시적으로(implicitly) 삭제되는 경우가 있습니다. 2. 예시 ㄱ. 기본 생성자 #include class foo{ public: }; int main(){ auto f = foo(); foo f2; foo f3(); return 0; } 위 예시 처럼, 기본 생성자는 일반적..

C++/개념(Concept) 2020.11.16

C++ 디자인: PImpl

C++ 디자인(Design): PImpl (Pointer to Implement) 1. 설명 Pimple 디자인은 헤더 파일에서는 실제 구현을 담당하는 클래스를 불완전한 타입으로 선언하고 이에 대한 포인터만 원래 클래스에 남겨두고, 소스 파일에서 구현 클래스를 정의하는 방법입니다. 그래서 Pointer to Implementation (구현(클래스)에 대한 포인터)라는 이름이 붙게 되었습니다. 이로 인해서 얻는 장점은 크게 2가지가 있습니다. 1. 컴파일 시간 단축 / ABI 호환성 보장 내부 구현이 바뀌어도, 헤더만 참조하는 파일은 재 컴파일이 필요하지 않음 2. 소스 코드 은닉 소스 파일을 빌드해서 배포할 시, 소스 코드를 은닉할 수 있습니다. 다만, 구현 클래스가 템플릿 특수화된 클래스거나, 팩토리..

C++ 템플릿(Template): SFINAE

C++ Template: SFINAE Substitution Failure Is Not An Error SFINAE는 C++ 템플릿 프로그래밍에서 자주 쓰이는 기법입니다. 컴파일러가 알맞은 함수를 추론(deduce) 하는 원리를 이용해, 받는 타입을 제한하거나 타입에 따라 행동을 다르게 할 때 주로 사용하게 됩니다. SFINAE is a technique that is often used in C++ Template Programming. It restrains function parameter types by using the mechanism of how the compiler deduces appropriate overloaded functions and calling the appropriate ..