10

x86에서 같은 배열의 인접한 요소에 동시에 쓰는 두 개의 다른 스레드를 갖는 것이 안전하지 않은 상황은 무엇입니까? 미친 메모리 모델을 가진 DS9K와 같은 일부 아키텍처에서는 워드 찢어짐이 발생할 수 있지만 x86 단일 바이트에서는 주소 지정이 가능하다는 것을 알고 있습니다. 예를 들어, D 프로그래밍 언어 real은 x86에서 80 비트 부동 소수점 유형입니다.Word에서 단어 찢기

real[] nums = new real[4]; // Assume new returns a 16-byte aligned block. 
foreach(i; 0..4) { 
    // Create a new thread and have it do stuff and 
    // write results to index i of nums. 
} 

참고 :이 같은 일을하는 것이 안전 할 것이다 나는이 안전하더라도, 그것은 때로는 성능을 저하로 이어지는, 캐시와 거짓 공유 문제를 일으킬 수 있다는 것을 알고있다. 그러나 유스 케이스의 경우, 필자는이 문제가 실제로 발생하지 않을 정도로 드문 경우가 있음을 염두에 둡니다.

편집 : 작성된 값을 다시 읽지 않아도됩니다. 어떤 값을 읽기 전에 이 동기화된다는 가정이 있습니다. 나는 을 쓰는 것만으로 안전을 중요하게 생각합니다.

+0

인접한 주소의 더러운 글을보고 있다고 생각하십니까? – BCS

답변

10

x86에는 일관된 캐시가 있습니다. 마지막으로 캐시 라인에 쓰는 프로세서가 전체를 가져 와서 캐시에 쓰기를합니다. 이렇게하면 해당 값에 기록 된 1 바이트 및 4 바이트 값이 원자 적으로 업데이트됩니다.

"안전"과 다릅니다. 프로세서가 각각 설계된 방식으로 해당 프로세서에 의해 바이트/DWORDS에 "소유"된 경우에만 업데이트가 올바르게 수행됩니다. 실제로 한 프로세서가 다른 사람이 작성한 값을 읽으려는 경우 동기화가 필요합니다.

또한 "효율적인"것과 다릅니다. 여러 프로세서가 캐시 라인의 다른 위치에 각각 쓸 수 있다면 캐시 라인은 CPU 사이에서 핑퐁 (ping-pong) 할 수 있으며 캐시 라인이 단일 CPU로 이동하여 거기에 머물러있을 때보 다 훨씬 비쌉니다. 일반적인 규칙은 프로세서 고유의 데이터를 자체 캐시 라인에 저장하는 것입니다. 물론 한 단어 만 쓰고 단 한 번만 쓰면 작업량이 캐시 라인 이동에 비해 중요 할 경우 성능을 인정할 수 있습니다.

+0

독서에 대한 요점에 대해 : 아이디어는 병렬지도와 같은 것을 사용하여 거대한 배열을 병렬로 채우는 것이 었습니다. 매핑 기능이 대부분의 시간을 소비하므로 쓰기 작업에 소요되는 시간은 무시할 수 있으며 캐시 라인은 작업 단위 경계 근처에서만 공유됩니다. 이 배열에서 값을 읽기 전에 일부 유형의 동기화가 사용됩니다. – dsimcha

1

내가 누락되었을 수 있지만 문제가 발생하지는 않을 것으로 예상됩니다. x86 아키텍처는 필요로하는 것만 씁니다. 지정된 값을 벗어난 쓰기 작업은 수행하지 않습니다. 캐시 스누핑은 캐시 문제를 처리합니다.

1

당신은 x86 특성에 대해 묻고 있지만, 당신의 예제는 고수준 언어입니다. D에 관한 특정 질문은 사용중인 컴파일러를 작성한 사람 또는 아마도 D 언어 사양에 의해서만 답변 될 수 있습니다. 예를 들어 Java에서는 배열 요소에 액세스 할 때 찢어지지 않아야합니다.

x86의 경우 조작의 원 자성은 섹션 8.1에서 Intel's Software Developer's Manual Volume 3A으로 지정됩니다. 그것에 따르면, 원자 저장소 운영은 모든 x86 CPU에 바이트 저장, 단어 정렬 단어 및 dword 정렬 dword 저장을 포함합니다. 또한 P6 및 이후 CPU에서 캐시 라인 내의 캐시 된 메모리에 대한 16-, 32- 및 64- 비트 액세스가 정렬되지 않았 음을 지정합니다.

관련 문제