2010-07-28 2 views
5

저는 x86 ASM에서 원자 적으로 값을 쓰는 방법을 알고 있습니다. 하지만 어떻게 읽습니까? LOCK 접두어는 mov와 함께 사용할 수 없습니다. x86 ASM에서 값을 원자 적으로 읽는 방법은 무엇입니까?

이 값을 증가시키기 위해, 내가 뭐하는 거지 :

lock inc dword ptr Counter 

가 어떻게 스레드 안전한 방법으로 카운터를 읽습니까?

답변

4

저는 어셈블리 전문가는 아니지만 워드 크기 (x86, 32 비트) 읽기/쓰기는 이미 원자이어야합니다.

증가분을 잠그는 이유는 읽기 및 쓰기이기 때문입니다.

+0

나는 당신이 옳다고 생각합니다. 그건 의미가 있습니다. 감사. – IamIC

+0

도움이된다면 답을 받아 드리는 것을 잊지 마십시오;) –

+4

항상 그렇지는 않습니다! 메모리 어드레스가 다중 CPU 유닛에서 두 번째 CPU를 사용하는 캐시에 있으면 읽기가 원자 적으로 보장되지 않습니다. 따라서 첫 번째 울타리 메모리 캐시 인 "LOCK CMPXCHG EAX, [var]"를 사용하십시오. –

1

간단한 읽기 때문에 대부분 정렬과 관련이 있습니다. 원자 판독을 보장하는 가장 쉬운 방법은 항상 "자연스런"정렬을 사용하는 것입니다. 즉, 정렬은 항목 크기만큼 커야합니다 (예 : 32 비트 항목은 32 비트 정렬 됨).

불일치 읽기는 반드시 원자적일 필요는 없습니다. 극단적 인 예를 들어, 첫 번째 바이트가 한 캐시 라인에 있고 다른 세 바이트가 다른 캐시 라인에있는 홀수 주소에서 32 비트 값을 읽는 것을 고려하십시오. 그러한 경우 원자 읽기는 본질적으로 불가능합니다.

(적어도 대부분의) 프로세서는 64 비트 폭의 메모리 버스를 사용하기 때문에 원자 적으로 읽을 수있는 최대 항목은 64 비트입니다.

5

나는 this 게시물에 당신에게 설명과 같이

는 페이지 경계는 인텔 코어 2 원자 수 을 보장 할 수 없습니다 버스 폭, 캐시 라인에 걸쳐 분할 캐시 메모리에 액세스합니다 듀오, Intel Core Duo, Pentium M, Pentium 4, Intel Xeon, P6 제품군, Pentium 및 Intel486 프로세서. 인텔 코어 2 듀오, 인텔 코어 듀오, 펜티엄 M, 펜티엄 4, 인텔 제온 및 P6 계열 프로세서는 외부 메모리 서브 시스템을 허용하는 버스 제어 신호 을 제공합니다. 분할 액세스를 원자 단위로 만듭니다. 그러나 정렬되지 않은 데이터 액세스는 프로세서의 성능에 심각한 영향을 미치므로 피해야합니다. 대상 값이 EAX의 결과가 대상 값이 다음이다 EQU하지 않을 경우 대상 값으로 EAX를 비교

LOCK  CMPXCHG EAX, [J] 

LOCK CMPXCHG 최초의 울타리 캐시 메모리를하고 이상 :

그래서 사용합니다.

EDIT : 링크 :

Intel® 64 and IA-32 Architectures Software Developer’s Manuals

에서 Volume 3A: System Programming Guide 검사 8.1.1

또한 확인 : Optimization Reference Manual section: CHAPTER 7 OPTIMIZING CACHE USAGE

+0

[J]가 메모리 포인터이기 때문에 컴파일되지 않습니다. 레지스터 값이어야합니다. 이것은 내가 잡을 수없는 캐치 22입니다. – IamIC

+1

나는 당신의 다른 포스트에서 값이 정렬되고 CPU의 버스 너비와 일치하는 한 이것이 실제로 문제가되지 않는다는 것을 안다. – IamIC

+0

@IAMIC : 버스 너비가 아닙니다. 인텔과 AMD가 보장하는 가장 낮은 공통 분모는 'mov'로드/저장이 [캐시 된 액세스의 경우 8 바이트 경계를 넘지 않는 경우] 원자 적이라는 것입니다.] (https://stackoverflow.com/a/36685056/224132) 또는 정렬되지 않은 경우 캐시되지 않은 경우 또는 dword 경계를 넘지 않는 16 비트 액세스 인 경우 또한'[J]'는 RIP- 상대 주소 지정 모드의 절대 또는 (x86-64에서) 단순하다. 그것은 이중 우회가 아닙니다. 그것은 잘 조립됩니다. MASM 구문은'[] '을 생략하는 경우가 많지만 MASM에서는 선택 사항이며 NASM에서는 필요합니다. –

1

다른 응답을 읽어 흥미 롭다. 나는 @GJ가 아마 돈에 있다고 생각한다.

수년 동안 32 비트 읽기 및 쓰기가 원자 적 이었다는 것이 항상 사실이었습니다. 최근에는 공격적인 캐싱으로 인해 더 이상 보장되지 않습니다.

나는 그것이 내가 C++, Java 또는 그와 나와 기계어 코드를 선호하는 이유라고 생각한다. 요즘은 기계 코드가 너무 복잡하여 쓰기가 어렵습니다 (많은 기술을 보유하기 위해). 운좋게도 오늘날의 최적화 컴파일러는 매우 훌륭하기 때문에 수동으로 최적화 된 어셈블러의 성능을 거의 필요로하지는 않습니다.

+0

C++은 CPU가 수행하는 것 이상의 메모리 의미론에 대해서는 보증하지 않으며, 휘발성이없는 Java도 보장하지 않습니다. –

+0

C++는 C (C11)와 마찬가지로 원자 유형 (C++ 11 항목)에 대한 원자 액세스를 보장 할 수 있습니다. –