ホームページ >バックエンド開発 >C++ >CAS を使用して C 11 にロックフリーの ABA カウンターを実装し、パフォーマンスのオーバーヘッドを最小限に抑えるにはどうすればよいですか?

CAS を使用して C 11 にロックフリーの ABA カウンターを実装し、パフォーマンスのオーバーヘッドを最小限に抑えるにはどうすればよいですか?

Susan Sarandon
Susan Sarandonオリジナル
2024-12-15 08:07:11775ブラウズ

How can I implement a lock-free ABA counter in C  11 using CAS and minimize performance overhead?

c 11 CAS で ABA カウンタを実装するにはどうすればよいですか?

2 つの値を同時にアトミックに更新するには、アトミックな隣接する構造体を作成します。 std::atomic を使用するとします。これを実装するために。その後、次のアクションが発生します:

  1. gcc コンパイルを通じて x86-64 プロセッサーでロック cmpxchg16b 命令を利用します。
  2. 効率を高めるためにインライン アセンブリを回避し、C 構文を優先します。
  3. 個々の構造体の効率的なロードを可能にするためにユニオンを使用する
  4. x86 アーキテクチャでのパフォーマンスの問題を防ぐために、16B (または 32 ビット ポインターの場合は 8B) のアライメントを確保します。
  5. cmpxchg16b は一貫してサポートされていなかったため、x86-64 ビルドには -mcx16 を使用してください。初期の x86-64 CPU。

注特に x86 CPU の場合、アトミック オブジェクトはロックフリーである必要があります。 gcc7 以降のようなコンパイラは、インライン ロック cmpxchg16b を使用する代わりに libatomic を呼び出す場合があります。このようなシナリオでは、次の点を考慮してください:

  • コンパイラーが、ペアのロック cmpxchg16b に頼らずに個々のメンバーを読み取るための効率的なコードを生成することを確認します。
  • 1 つの共用体メンバーにアクセスする際に、変更後の別の変更は実装用に明確に定義されています。これは GNU C では合法ですが、ISO C に厳密に準拠している場合は、未定義の動作が発生する可能性があります。
  • 位置がずれていると、x86 アーキテクチャでパフォーマンスが低下する可能性があるため、オブジェクトが適切に位置合わせされていることを確認してください。
  • ポインターより大きいアトミック オブジェクトは x86-64 でロックを使用する可能性があるため、32 ビット ポインターのアラインメントを維持します。 CPU。

これらの特性を示す C 11 コードの例を次に示します。

#include <atomic>
#include <stdint.h>

using namespace std;

struct node {
  struct alignas(2*sizeof(node*)) counted_ptr {
    node *    ptr;
    uintptr_t count;  // use pointer-sized integers to avoid padding
  };

  // hack to allow reading just the pointer without lock-cmpxchg16b,
  // but still without any C++ data race
  struct counted_ptr_separate {
    atomic<node *>    ptr;
    atomic<uintptr_t> count_separate;  // var name emphasizes that accessing this way isn't atomic with ptr
  };

  static_assert(sizeof(atomic<counted_ptr>) == sizeof(counted_ptr_separate), "atomic<counted_ptr> isn't the same size as the separate version; union type-punning will be bogus");
  // TODO: write member functions to read next.ptr or read/write next_and_count

  union {  // anonymous union: the members are directly part of struct node
    alignas(2*sizeof(node*)) atomic<counted_ptr> next_and_count;
    counted_ptr_separate  next;
  };
};

要約すると、2 つの値を同時にアトミックに変更するには、慎重な設計、コンパイラの考慮事項、およびアライメントの最適化が必要です。 。これらのガイドラインに従うことで、効率的で正しいコードを使用して C 11 にロックフリーの ABA カウンターを実装できます。

以上がCAS を使用して C 11 にロックフリーの ABA カウンターを実装し、パフォーマンスのオーバーヘッドを最小限に抑えるにはどうすればよいですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。