문제

다른 주에 나는 작은 스레드 클래스와 일방 통신 메시지 파이프를 썼다. 스레드 간의 통신 (나사당 두 파이프, 분명히 양방향 통신을 위해). Athlon 64 x2에서 모든 것이 잘 작동했지만 두 스레드가 동일한 변수를보고 있으면 모든 문제가 발생하고 각 코어 의이 변수에 대한 로컬 캐시 값이 동기화되지 않은 경우 문제가 발생할지 궁금했습니다.

나는 알고있다 휘발성 물질 키워드는 변수가 메모리에서 새로 고침되도록 강요되지만 멀티 코어 x86 프로세서에서 모든 코어의 캐시가 동기화되도록하는 방법이 있습니까? 이것은 내가 걱정해야 할 것인가, 아니면 휘발성 물질 그리고 경량 잠금 메커니즘을 올바르게 사용하여 (_In

나는 이미 중요한 섹션, 뮤트, 이벤트 등을 알고 있고 사용했습니다. 캐시 일관성을 시행하는 데 어떤 힘이나 사용될 수 있는지 알지 못하는 x86 내재가 있는지 궁금합니다.

도움이 되었습니까?

해결책

volatile 코드가 값을 다시 읽도록 강요하면 값을 읽는 위치를 제어 할 수 없습니다. 값이 최근 코드에 의해 읽은 경우 캐시에있을 것입니다.이 경우 휘발성은 메모리가 아닌 캐시에서 다시 읽도록 강요합니다.

x86에는 캐시 일관성 지침이 많지 않습니다. 프리 페치 지침이 있습니다 prefetchnta, 그러나 그것은 메모리 주문 시맨틱에 영향을 미치지 않습니다. L2를 오염시키지 않고 L1 캐시에 값을 가져와 구현되었지만 공유 된 대규모 인텔 디자인에 더 복잡합니다. 포함한 L3 캐시.

x86 CPU는 변형을 사용합니다 MESI 프로토콜 (인텔의 경우 Mesif, AMD 용 Moesi) 캐시를 서로 일관성있게 유지합니다 (다른 코어의 개인 L1 캐시 포함). 캐시 라인을 작성하려는 핵심은 다른 코어가 공유 상태에서 수정 된 상태로 자체 사본을 변경하기 전에 사본을 무효화하도록 강요해야합니다.


X86 하중/스토어에는 X86에서 데이터를 생성하고 다른 스레드에서 데이터를 생성하기 위해 펜스 지침 (Mfence와 같은)이 필요하지 않습니다. Semantics를 획득/릴리스합니다 내장. 순차적 일관성을 얻으려면 Mfence (전체 장벽)가 필요합니다. (이 답변의 이전 버전은 그것을 제안했습니다 clflush 필요했습니다. 잘못되었습니다).

예방해야합니다 컴파일 타임 재주문, C ++의 메모리 모델이 약점이 있으므로. volatile 이것을하는 오래되고 나쁜 방법입니다. C ++ 11 STD :: Atomic은 잠금 코드를 작성하는 훨씬 더 나은 방법입니다.

다른 팁

X86 프로세서가 사용하는 MESI 프로토콜로 인해 캐시 일관성은 코어간에 보장됩니다. 외부 하드웨어를 처리 할 때 메모리 일관성에 대해 걱정하면됩니다.이 하드웨어는 메모리에 액세스 할 수있는 동안 데이터가 여전히 코어 캐시에 앉아 있습니다. 그러나 텍스트는 사용자 랜드에서 프로그래밍하고 있다고 제안하기 때문에 여기서는 여기에서 당신의 경우처럼 보이지 않습니다.

캐시 일관성에 대해 걱정할 필요가 없습니다. 하드웨어가 처리 할 것입니다. 걱정해야 할 것은 캐시 일관성으로 인한 성능 문제입니다.

Core#1이 변수에 쓰면 다른 코어에서 캐시 라인의 다른 모든 사본을 무효화합니다 (가져와야하기 때문에 독점 소유권 상점을 커밋하기 전에 캐시 라인의. Core#2가 동일한 변수를 읽으면 캐시에서 누락됩니다 (Core#1이 공유 수준의 캐시 수준까지 이미 작성하지 않는 한).

전체 캐시 라인 (64 바이트)을 메모리에서 읽거나 공유 캐시에 다시 작성한 다음 Core#2로 읽음)를 읽어야하므로 성능 비용이 발생합니다. 이 경우 피할 수 없습니다. 이것이 원하는 행동입니다.


문제는 동일한 캐시 라인에 여러 변수가있을 때 프로세서가 동일한 캐시 라인 내에서 다른 변수를 읽거나 쓰는 경우에도 캐시를 동기화하는 데 추가 시간을 소비 할 수 있다는 것입니다.

이러한 변수가 동일한 캐시 라인에 있지 않도록하여 비용을 피할 수 있습니다. 이 효과는 다음과 같습니다 허위 공유 프로세서가 실제로 스레드간에 공유되지 않은 객체 값을 동기화하도록 강요하기 때문에.

휘발성은 그것을하지 않습니다. C ++에서 휘발성은 메모리 대신 레지스터에 변수를 저장하거나 완전히 제거하는 것과 같은 컴파일러 최적화에만 영향을 미칩니다.

사용중인 컴파일러를 지정하지 않았지만 Windows에있는 경우 살펴보십시오. 이 기사는 여기에 있습니다. 또한 사용 가능한 S를 살펴보십시오ynchronization 기능은 여기에 있습니다. 일반적으로 주목하고 싶을 수도 있습니다 volatile 당신이 원하는 일을하기에는 충분하지 않지만 VC 2005와 2008에 따라 읽기 및 쓰기 주위에 암시 된 메모리 장벽을 추가하는 비표준 의미가 추가되었습니다.

휴대가되기를 원한다면 앞서 훨씬 더 어려운 길을 가질 것입니다.

현대 메모리 아키텍처를 설명하는 일련의 기사가 있습니다. 여기, 포함 인텔 코어 2 캐시 그리고 더 많은 현대 건축 주제.

기사는 매우 읽기 쉽고 잘 설명되어 있습니다. 즐기다 !

귀하의 질문에는 몇 가지 하위 질문이 있으므로 내 지식을 최대한 활용할 수 있습니다.

  1. 현재 C ++에서 잠금 장치 상호 작용을 구현하는 휴대용 방법은 없습니다. C ++ 0X 제안은 Atomics 라이브러리를 소개하여이를 해결합니다.
  2. 휘발성은 멀티 코어에 원자력을 제공하는 것이 보장되지 않으며 그 구현은 공급 업체 별입니다.
  3. X86에서는 멀티 스레드 코드를 중단 할 수있는 일부 컴파일러 최적화를 방지하기 위해 공유 변수를 휘발성으로 선언하는 것을 제외하고는 특별한 작업을 수행 할 필요가 없습니다. 휘발성은 컴파일러에게 값을 캐시하지 말라고 지시합니다.
  4. 변수 변수가있는 X86에서도 작동하지 않는 일부 알고리즘 (Dekker)이 있습니다.
  5. 스레드 간 데이터에 대한 액세스를 전달하는 것이 프로그램의 주요 성능 병목 현상이라는 것을 확실히 알지 못하면 잠금 솔루션에서 멀리 떨어져 있습니다. 값 또는 잠금으로 전달 데이터를 사용하십시오.

다음은 사용과 관련하여 좋은 기사입니다. volatile 스레드 프로그램이 있습니다.

다중 스레드 프로그래밍에는 거의 쓸모가 없습니다.

허브 셔터는 간단한 것처럼 보였다 제안하다 두 변수는 별도의 캐시 라인에 상주해야합니다. 그는 그의 자물쇠와 노드 포인터 사이의 패딩으로 동시 대기열에서 이것을합니다.

편집 : 인텔 컴파일러 또는 GCC를 사용하는 경우 원자 내장, 가능하면 캐시를 선점하는 데 최선을 다하는 것 같습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top