Skip to content

Latest commit

 

History

History
131 lines (106 loc) · 4.75 KB

hardware_destructive_interference_size.md

File metadata and controls

131 lines (106 loc) · 4.75 KB

hardware_destructive_interference_size

  • new[meta header]
  • std[meta namespace]
  • variable[meta id-type]
  • cpp17[meta cpp]
namespace std {
  inline constexpr std::size_t hardware_destructive_interference_size = implementation-defined;
}

概要

2つのオブジェクトに並行アクセスする際に、パフォーマンス低下を避けられる最小アライメントサイズ。

struct keep_apart {
  std::atomic<int> cat;
  std::atomic<int> dog;
};

このような構造体がある場合、catdogが同じキャッシュラインに乗ることがある。スレッド1ではcat変数、スレッド2ではdog変数を操作するような状況で、それぞれが共通のキャッシュを無効化してしまうパフォーマンス劣化の問題が起こりえる。こういった状況を「false sharing」という。

hardware_destructive_interference_sizeは、false sharingを回避するための、変数ごとにキャッシュラインを分けられる最小アライメントサイズである。

struct keep_apart {
  alignas(std::hardware_destructive_interference_size) std::atomic<int> cat;
  alignas(std::hardware_destructive_interference_size) std::atomic<int> dog;
};
  • std::hardware_destructive_interference_size[color ff0000]

備考

  • この変数の値は、alignof(max_align_t)以上である
  • 実装上、hardware_constructive_interference_sizehardware_destructive_interference_sizeは同値になるはずだが、利用目的によって名前を使い分けるために分かれている

#include <iostream>
#include <new>
#include <thread>
#include <vector>

struct X {
  alignas(std::hardware_destructive_interference_size) int a;
  alignas(std::hardware_destructive_interference_size) int b;
};

struct IndividualCacheInt {
  alignas(std::hardware_destructive_interference_size) int value;
};

int main()
{
  std::cout << "hardware_destructive_interference_size : "
            << std::hardware_destructive_interference_size
            << std::endl;

  // 構造体内のメンバ変数aとbを、それぞれ別なキャッシュラインに乗せる
  {
    X x;
    x.a = 0;
    x.b = 0;
    std::thread t1{[&x]{
      for (int i = 0; i < 100; ++i) {
        ++x.a;
      }
    }};

    std::thread t2{[&x]{
      for (int i = 0; i < 100; ++i) {
        ++x.b;
      }
    }};

    t1.join();
    t2.join();
  }

  // 連続したメモリの各要素を、個別のキャッシュに乗せる
  {
    std::vector<IndividualCacheInt> v{10};
    std::vector<std::thread> threads;
    for (std::size_t i = 0; i < v.size(); ++i) {
      threads.push_back(std::thread{[&v, i]{
        for (int j = 0; j < 100; ++j) {
          ++v[i].value;
        }
      }});
    }

    for (std::thread& t : threads) {
      t.join();
    }
  }
}
  • std::hardware_destructive_interference_size[color ff0000]
  • threads.push_back[link /reference/vector/vector/push_back.md]

出力例

hardware_destructive_interference_size : 64

バージョン

言語

  • C++17

処理系

参照