>백엔드 개발 >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 카운터를 어떻게 구현할 수 있나요?

두 값을 동시에 원자적으로 업데이트하려면 원자적이고 인접한 구조체를 만듭니다. std::atomic 이것을 구현하기 위해. 그러면 다음 작업이 수행됩니다.

  1. gcc 컴파일을 통해 x86-64 프로세서에서 잠금 cmpxchg16b 명령을 활용합니다.
  2. 인라인 어셈블리를 피하고 효율성을 위해 C 구문을 선호합니다.
  3. Union을 사용하여 개별 구조체 멤버를 효율적으로 로드할 수 있습니다.
  4. 다음을 보장하세요. 16B(또는 32비트 포인터의 경우 8B) 정렬을 통해 x86 아키텍처의 성능 문제를 방지합니다.
  5. 초기 x86-64 CPU에서는 cmpxchg16b가 일관되게 지원되지 않았으므로 x86-64 빌드에는 -mcx16을 사용하세요.

특히 x86의 경우 원자 객체에는 잠금이 없어야 합니다. CPU. gcc7 이상과 같은 컴파일러는 인라인 잠금 cmpxchg16b를 사용하는 대신 libatomic을 호출할 수 있습니다. 이러한 시나리오에서는 다음을 고려하십시오.

  • 컴파일러가 쌍의 cmpxchg16b 잠금을 사용하지 않고 개별 멤버를 읽기 위한 효율적인 코드를 생성하는지 확인하세요.
  • 하나의 공용체 멤버에 액세스하는지 확인하세요. 다른 것을 수정한 후 구현을 위해 잘 정의되어 있습니다. 이는 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;
  };
};

요약하자면 두 값을 동시에 원자적으로 수정하려면 신중한 설계, 컴파일러 고려 사항 및 정렬 최적화가 필요합니다. . 이러한 지침을 따르면 효율적이고 올바른 코드를 사용하여 C 11에서 잠금 없는 ABA 카운터를 구현할 수 있습니다.

위 내용은 CAS를 사용하여 C 11에서 잠금 없는 ABA 카운터를 구현하고 성능 오버헤드를 최소화하려면 어떻게 해야 합니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.