Namespaces
Variants

std:: hardware_destructive_interference_size, std:: hardware_constructive_interference_size

From cppreference.net
Concurrency support library
Threads
(C++11)
(C++20)
hardware_destructive_interference_size hardware_constructive_interference_size
(C++17) (C++17)
this_thread namespace
(C++11)
(C++11)
Cooperative cancellation
Mutual exclusion
Generic lock management
Condition variables
(C++11)
Semaphores
Latches and Barriers
(C++20)
(C++20)
Futures
(C++11)
(C++11)
(C++11)
Safe reclamation
Hazard pointers
Atomic types
(C++11)
(C++20)
Initialization of atomic types
(C++11) (deprecated in C++20)
(C++11) (deprecated in C++20)
Memory ordering
(C++11) (deprecated in C++26)
Free functions for atomic operations
Free functions for atomic flags
헤더 파일에 정의됨 <new>
inline constexpr std:: size_t
hardware_destructive_interference_size = /*implementation-defined*/ ;
(1) (C++17부터)
inline constexpr std:: size_t
hardware_constructive_interference_size = /*implementation-defined*/ ;
(2) (C++17부터)
1) 거짓 공유(false sharing)를 방지하기 위한 두 객체 간의 최소 오프셋. 최소한 alignof ( std:: max_align_t )
struct keep_apart
{
    alignas(std::hardware_destructive_interference_size) std::atomic<int> cat;
    alignas(std::hardware_destructive_interference_size) std::atomic<int> dog;
};
2) 참조 공유를 촉진하기 위한 연속 메모리의 최대 크기. 최소한 alignof ( std:: max_align_t )
struct together
{
    std::atomic<int> dog;
    int puppy;
};
struct kennel
{
    // Other data members...
    alignas(sizeof(together)) together pack;
    // Other data members...
};
static_assert(sizeof(together) <= std::hardware_constructive_interference_size);

참고 사항

이 상수들은 L1 데이터 캐시 라인 크기에 접근하는 이식 가능한 방법을 제공합니다.

기능 테스트 매크로 표준 기능
__cpp_lib_hardware_interference_size 201703L (C++17) constexpr std :: hardware_constructive_interference_size

constexpr std :: hardware_destructive_interference_size

예제

이 프로그램은 주어진 전역 객체들의 데이터 멤버에 원자적으로 기록하는 두 개의 스레드를 사용합니다. 첫 번째 객체는 하나의 캐시 라인에 적합하여 "하드웨어 간섭"을 유발합니다. 두 번째 객체는 데이터 멤버를 별도의 캐시 라인에 유지하므로 스레드 기록 후 발생할 수 있는 "캐시 동기화"가 방지됩니다.

#include <atomic>
#include <chrono>
#include <cstddef>
#include <iomanip>
#include <iostream>
#include <mutex>
#include <new>
#include <thread>
#ifdef __cpp_lib_hardware_interference_size
    using std::hardware_constructive_interference_size;
    using std::hardware_destructive_interference_size;
#else
    // x86-64에서 64바이트 │ L1_CACHE_BYTES │ L1_CACHE_SHIFT │ __cacheline_aligned │ ...
    constexpr std::size_t hardware_constructive_interference_size = 64;
    constexpr std::size_t hardware_destructive_interference_size = 64;
#endif
std::mutex cout_mutex;
constexpr int max_write_iterations{10'000'000}; // 벤치마크 시간 튜닝
struct alignas(hardware_constructive_interference_size)
OneCacheLiner // 하나의 캐시 라인을 차지함
{
    std::atomic_uint64_t x{};
    std::atomic_uint64_t y{};
}
oneCacheLiner;
struct TwoCacheLiner // 두 개의 캐시 라인을 차지함
{
    alignas(hardware_destructive_interference_size) std::atomic_uint64_t x{};
    alignas(hardware_destructive_interference_size) std::atomic_uint64_t y{};
}
twoCacheLiner;
inline auto now() noexcept { return std::chrono::high_resolution_clock::now
**변역 결과:**
HTML 태그와 속성은 그대로 유지되었으며, C++ 관련 용어(std::chrono::high_resolution_clock::now)는 번역되지 않았습니다.(); }
template<bool xy>
void oneCacheLinerThread()
{
    const auto start{now()};
    for (uint64_t count{}; count != max_write_iterations; ++count)
        if constexpr (xy)
            oneCacheLiner.x.fetch_add(1, std::memory_order_relaxed);
        else
            oneCacheLiner.y.fetch_add(1, std::memory_order_relaxed);
    const std::chrono::duration
**번역 결과:**
std::chrono::duration
**번역 설명:**
- HTML 태그와 속성은 그대로 유지
- C++ 표준 라이브러리 용어(std::chrono::duration)는 번역하지 않음
- 태그 내의 모든 텍스트와 클래스 속성은 원본 그대로 보존<double, std::milli> elapsed{now() - start};
    std::lock_guard lk{cout_mutex};
    std::cout << "oneCacheLinerThread() spent " << elapsed.count() << " ms\n";
    if constexpr (xy)
        oneCacheLiner.x = elapsed.count();
    else
        oneCacheLiner.y = elapsed.count();
}
template<bool xy>
void twoCacheLinerThread()
{
    const auto start{now()};
    for (uint64_t count{}; count != max_write_iterations; ++count)
        if constexpr (xy)
            twoCacheLiner.x.fetch_add(1, std::memory_order_relaxed);
        else
            twoCacheLiner.y.fetch_add(1, std::memory_order_relaxed);
    const std::chrono::duration
(설명: HTML 태그와 속성은 번역하지 않고, C++ 관련 용어(std::chrono::duration)는 원문을 유지하며, 태그 내부의 텍스트도 그대로 보존했습니다)<double, std::milli> elapsed{now() - start};
    std::lock_guard lk{cout_mutex};
    std::cout << "twoCacheLinerThread() spent " << elapsed.count() << " ms\n";
    if constexpr (xy)
        twoCacheLiner.x = elapsed.count();
    else
        twoCacheLiner.y = elapsed.count();
}
int main()
{
    std::cout << "__cpp_lib_hardware_interference_size "
#   ifdef __cpp_lib_hardware_interference_size
        "= " << __cpp_lib_hardware_interference_size << '\n';
#   else
        "is not defined, use " << hardware_destructive_interference_size
                               << " as fallback\n";
#   endif
    std::cout << "hardware_destructive_interference_size == "
              << hardware_destructive_interference_size << '\n'
              << "hardware_constructive_interference_size == "
              << hardware_constructive_interference_size << "\n\n"
              << std::fixed << std::setprecision(2)
              << "sizeof( OneCacheLiner ) == " << sizeof(OneCacheLiner) << '\n'
              << "sizeof( TwoCacheLiner ) == " << sizeof(TwoCacheLiner) << "\n\n";
    constexpr int max_runs{4};
    int oneCacheLiner_average{0};
    for (auto i{0}; i != max_runs; ++i)
    {
        std::thread th1{oneCacheLinerThread<0>};
        std::thread th2{oneCacheLinerThread<1>};
        th1.join();
        th2.join();
        oneCacheLiner_average += oneCacheLiner.x + oneCacheLiner.y;
    }
    std::cout << "평균 T1 시간: "
              << (oneCacheLiner_average / max_runs / 2) << " ms\n\n";
    int twoCacheLiner_average{0};
    for (auto i{0}; i != max_runs; ++i)
    {
        std::thread th1{twoCacheLinerThread<0>};
        std::thread th2{twoCacheLinerThread<1>};
        th1.join();
        th2.join();
        twoCacheLiner_average += twoCacheLiner.x + twoCacheLiner.y;
    }
    std::cout << "평균 T2 시간: "
              << (twoCacheLiner_average / max_runs / 2) << " ms\n\n"
              << "Ratio T1/T2:~ "
              << 1.0 * oneCacheLiner_average / twoCacheLiner_average << '\n';
}

가능한 출력:

__cpp_lib_hardware_interference_size = 201703
hardware_destructive_interference_size == 64
hardware_constructive_interference_size == 64
sizeof( OneCacheLiner ) == 64
sizeof( TwoCacheLiner ) == 128
oneCacheLinerThread() spent 517.83 ms
oneCacheLinerThread() spent 533.43 ms
oneCacheLinerThread() spent 527.36 ms
oneCacheLinerThread() spent 555.69 ms
oneCacheLinerThread() spent 574.74 ms
oneCacheLinerThread() spent 591.66 ms
oneCacheLinerThread() spent 555.63 ms
oneCacheLinerThread() spent 555.76 ms
평균 T1 시간: 550 ms
twoCacheLinerThread() spent 89.79 ms
twoCacheLinerThread() spent 89.94 ms
twoCacheLinerThread() spent 89.46 ms
twoCacheLinerThread() spent 90.28 ms
twoCacheLinerThread() spent 89.73 ms
twoCacheLinerThread() spent 91.11 ms
twoCacheLinerThread() spent 89.17 ms
twoCacheLinerThread() spent 90.09 ms
평균 T2 시간: 89 ms
비율 T1/T2:~ 6.16

참고 항목

구현체가 지원하는 동시 스레드 수를 반환합니다
( std::thread 의 public static 멤버 함수)
구현체가 지원하는 동시 스레드 수를 반환합니다
( std::jthread 의 public static 멤버 함수)