2017-12-24 46 views
10

나는 이런 식으로 물어 보는 것이 가장 좋을지 궁금해서이 질문을 Meta (https://meta.stackexchange.com/questions/304981)에서 물어 보았으므로 여기서 설명했다.absl :: Mutex의 조건부 임계 섹션이 독자 깨우침을 처리하는 방법

absl::Mutex (https://github.com/abseil/abseil-cpp/blob/master/absl/synchronization/mutex.h)으로 조건부 임계 섹션을 Google에 구현할 때 어떤 최적화가 이루어 졌는지 궁금합니다. 특히 나는 독자의 상태가 사실이되었을 때 어떻게 독자의 깨우기를 처리하는지 궁금해하고있었습니다. 그들은 대기자 명단에있는 다른 모든 독자들도 깨 웁니까? This line은 그들이하는 일을 신호로 보입니다. 그럴 때마다 O (n)이 횡단 될 위험이없고 쓰기 우선 순위 뮤텍스로 무리가 우뢰에 떨어질 위험이 있습니까?

+0

mutex.cc의 포함 파일을 읽는 것만으로도 pthread 또는 window.h를 사용할 수 있습니다. 그 높은 수준의 스레딩 라이브러리를 사용하면 아마 아무 것도 할 수 없습니다. 이것이 스레드를 깨우는 시스템입니다. 하위 레벨 코드를 사용하면 깨어있는 사람을 제어 할 수 있습니다 (또는 적어도 일부는'man 2 futex'를 참조하십시오). 하위 레이어가 없다면 거기에 없을 문제를 해결하기 위해 존재하는 슈퍼 레이어로 래퍼 주위에이 래퍼를 읽는 데 시간을 낭비하지 마십시오! – Oliv

+0

'futex' (리눅스에서)는 가능한 것의 우주를 제약 할 것입니다. 그러면 그 주위에 빌드 된 것이 있습니다 (뮤텍스, 세마포어 등). – Oliv

답변

4

디자인 최적화와 구현 최적화의 차이점을 설명하는 것이 중요하다고 생각합니다. absl ::은보다 최적화 된 구성 요소를 제공하는 것과는 대조적으로 이러한 디자인을 지원하는 구현을 제공함으로써 더 나은 디자인을 우선시하는 것으로 보입니다. 때로는 더 좋은 디자인은 서투른 디자인보다 본질적으로 성능이 뛰어나므로 결과가 두 요소 (시너지)에 최적화됩니다. Absiel.io가 이에 대해 자세히 설명합니다.

소스를 보면, absl은 보류중인 독자에게 방송하지 않으려면 마술으로 보이지 않으므로 천둥 무리가 계속 문제가됩니다. 일반적으로 구현은 그 문제를 의미있는 방식으로 해결할 수 없습니다. 그것은 디자인 문제입니다.

조건을 잠금의 일부로 포함하면 absl : ​​프로그래머가 해당 문제를 피하거나 설계 할 수 있습니다. 아직 무리가 있지만 잠금 구현으로 인해 희박해질 수 있습니다 plan 9 nod here. 마스크의 비트와 같이 각성의 원인을 잘 디자인하면 퍼포먼스에 영향을 미치는 가짜 웨이크 업을 걱정하지 않고 안전하게 공유/단독 잠금을 사용할 수 있습니다.

이것은 '디자인 최적화'의 핵심입니다.이 문제는 소스에서보다 명확하게 설명되며 결과 구현은 다른 것보다 더 높은 품질 (성능, 확장, ...)입니다.

플랜 9. 조건 변수는 유닉스 커널의 sleep (시간이 아닌)과 wakeup의 개념과 같습니다. 객체가 필요한 상태에 있지 않음을 감지하면 객체를 해당 상태로 가져 오기 시작하기 위해 몇 가지 작업을 수행 한 다음 해당 상태가 될 때까지 기다립니다. 예를 들어, 캐시에서 오브젝트를 검색 할 수 있으며, 발견되지 않은 경우 올바르지 않은 오브젝트를 작성하여 유효하게 만들 것을 요청할 수 있습니다. 이렇게하면 모든 캐시 참여자간에 일종의 대칭이 허용됩니다. 즉, 객체를 잠그고 상태를 평가하거나 업데이트 한 다음 객체를 잠금 해제하고 추가 변경을 기다립니다.

못생긴 문제는 다음과 같은 점이 있다는 것입니다. 동시에 같은 작업이없고 b : 잠금 처리가 오류가 발생하기 쉽습니다 (다른 잠금을 갖고 있습니까? 교착 상태가 될 수 있습니까?). 프로그램에 잘 표현되어 있지 않습니다. . Plan9의 sleep과 wakeup은 이들을 우아하게 병합했기 때문에 조건을 검사 한 시점에서 아무도 해당 객체에 영향을 줄 수 없습니다. 실제로, 참조 된 종이의 요점은 그 단순한 계약을 집행하는 것이 얼마나 힘든가하는 것입니다. 다중 처리 환경에서 복잡한 계약은 피해야합니다. for example.

중요한 최적화 (absl :)는 오브젝트가 잘못된 상태에 있는지를 판별하기 위해 값 비싼 컨텍스트 전환 조작을 수행 할 필요가 없다는 것입니다. 그런 다음 다시 절전 모드로 돌아갑니다. 깨우도록 선택한 코드가 개체 상태가 관심을 가질만한 상태인지 확인할 수 있다면 훨씬 좋습니다. 함수 호출/메소드 호출은 컨텍스트 스위치보다 100 배 빠릅니다.

AbslThis section은 웨이크 업 후보자가 선택되는 방법과 그룹이 도태되는 방법을 모두 다룹니다. This section은 브로드 캐스트를 생성합니다.

그래서 이전 섹션에서는 웨이터 목록에서 요소를 선택하고 후자 섹션에서 요소를 깨 웁니다. 2203 라인의 else 조건을 보면 작가가리스트를 종료하는 방법을 보여줍니다. w_walk-> wake가 참이 아니며 wr_wait가 설정되었습니다. 또한 2015 년과 2023 년의 초기 테스트는 쓰기 깨우기 인 경우이 목록 작성을 방해합니다.

모니터

obj.enter(); 
while (obj.state != StateIWant) { 
    obj.wait(); 
} 
... 
obj.exit(); 

가드 실행 조건이 스레드 요구. 이 차단 된 스레드를 이동하는 동작은 조건 실행 비용의 1000 배가 될 수 있습니다. 반면 :

obj.wait(^{return obj.state == StateIWant;}); 
... 
obj.exit(); 

따라서 비싼 상황이 쓸모없는 경우에 스위치를 피하고, 스레드가 대기 (. 즉, 호출 종료)를 허용 한 쪽의 맥락에서 조건을 평가하기 위해 대기 호출을 허용하는 것입니다.

+0

"지정된 waker"기능은 코드에 어떤 용도로 사용됩니까? https://github.com/abseil/abseil-cpp/blob/be40fdf1a86f4956d2f8125a7b6bd6d34e133c2d/absl/synchronization/mutex.cc#L593 스레드가 깨어나는 것과 관련이 있다고 생각합니다. – Curious

+0

누군가에게 문을 여는 적이 있습니까? 한 줄의 사람들에게 문을 여는 것을 발견 했습니까? 내가 그것을 정확하게 읽는다면, 그것은 약간 그 것이다. 이 경우 문은 기본 동기화 서비스 (예 : Futex, Win32, SEM, ...)이며 코드는 더 나은 성능을 위해이를 피하려고 시도합니다. 즉, 이런 일이 일어나는 경우를 상상할 수는 없지만 때로는 사람들의 행로를 기다리고 있습니다. – mevets