그것은 모든 multiprocessing
가 RLock
을 구현 한 방법에 따라 달라집니다. 나는 멀티 프로세싱 호스트 전체에서 작동 할 수 있다는 것을 알고 있습니다. 이는 동기화 프리미티브가 소켓에서 작동 할 수 있음을 의미합니다. 이것이 사실이라면 많은 (가변적 인) 대기 시간을 초래할 것입니다.
그래서 실험을했습니다.
이 실행
#!/usr/bin/env python
import multiprocessing
from time import sleep
lock = multiprocessing.RLock()
def noop(myname):
# nonlocal lock
sleep(0.5)
print myname, "acquiring lock"
with lock:
print myname, "has lock"
sleep(0.5)
print myname, "released lock"
sProc1 = multiprocessing.Process(target=noop, args=('alice',))
sProc2 = multiprocessing.Process(target=noop, args=('bob',))
sProc1.start()
sProc2.start()
sProc1.join()
sProc2.join()
는 출력이 보입니다 :
여기에 (모든 잠금이 같은 프로세스 내에서 어디에있는 빠른 경로를 방지하기 위해) 하나 개 이상의 프로세스에서 사용하고 RLock
의 검은 제비 갈매기 예입니다 다음과 같이하십시오 :
alice acquiring lock
alice has lock
bob acquiring lock
alice released lock
bob has lock
bob released lock
위도 있으므로 strace을 통한 시스템 호출 추적으로 실행하십시오.
아래의 명령에서 -ff
옵션은 도구가 "fork()
"을 따르는 호출 즉, 주 인터페이스에서 시작한 모든 프로세스를 추적합니다. 간결하게하기 위해 나는 -e trace=futex,write
도 사용하고 있습니다.이 필터는 게시하기 전에 작성한 결론에 따라 출력을 필터링합니다. 일반적으로 -e
옵션없이 실행하고 텍스트 편집기/grep
을 사용하여 사실 이후에 발생한 문제를 조사합니다. 인쇄의 패턴에서
# strace -ff -e trace=futex,write ./traceme.py
futex(0x7fffeafe29bc, FUTEX_WAIT_BITSET_PRIVATE|FUTEX_CLOCK_REALTIME, 1, NULL, 7fb92ac6c700) = -1 EAGAIN (Resource temporarily unavailable)
futex(0x7fb92a8540b0, FUTEX_WAKE_PRIVATE, 2147483647) = 0
futex(0x7fb92aa7131c, FUTEX_WAKE_PRIVATE, 2147483647) = 0
write(3, "\1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 32) = 32
Process 25873 attached
Process 25874 attached
Process 25872 suspended
[pid 25873] write(1, "alice acquiring lock\n", 21alice acquiring lock
) = 21
[pid 25873] write(1, "alice has lock\n", 15alice has lock
) = 15
[pid 25874] write(1, "bob acquiring lock\n", 19bob acquiring lock
) = 19
[pid 25874] futex(0x7fb92ac91000, FUTEX_WAIT, 0, NULL <unfinished ...>
[pid 25873] futex(0x7fb92ac91000, FUTEX_WAKE, 1 <unfinished ...>
[pid 25874] <... futex resumed>) = 0
[pid 25873] <... futex resumed>) = 1
[pid 25874] write(1, "bob has lock\n", 13 <unfinished ...>
bob has lock
[pid 25873] write(1, "alice released lock\n", 20 <unfinished ...>
alice released lock
[pid 25874] <... write resumed>) = 13
[pid 25873] <... write resumed>) = 20
Process 25872 resumed
Process 25873 detached
[pid 25872] --- SIGCHLD (Child exited) @ 0 (0) ---
Process 25872 suspended
[pid 25874] write(1, "bob released lock\n", 18bob released lock
) = 18
Process 25872 resumed
Process 25874 detached
--- SIGCHLD (Child exited) @ 0 (0) ---
은 (
write()
) 메시지 및 블록 나중에 이력서
futex
전화, 그것은
RLock
가
futex
, 또는 "빠른 사용자 공간 뮤텍스"를 사용하여 구현되는 것이 분명 보인다. 이름에서 알 수 있듯이 이것은 동기화에 좋은 선택입니다.
futex
과 같이 시스템 호출에서 프로세스가 차단되면 모든 의도와 목적으로 프로세스가 I/O를 차단합니다.
이 모든 내용은 multiprocessing.RLock
이 효율적이고 어떻게 설계 되었는가를 나타냅니다. 따라서 동기화를 사용할 때 응용 프로그램의 성능이 예상보다 낮 으면 알고리즘이 잘못 될 가능성이 있습니다.
독립 엔터티 (즉, 프로세스 또는 호스트)간에 동기화하려면 변경 사항이있을 경우 서로 계속 요청해야합니다. 이것은 모든 엔티티가 동일한 데이터를 볼 수 있도록 캐시를 우회하는 것과 같이 많은 미묘한 비용이 듭니다. 캐싱되지 않은 메모리에 액세스하면 성능이 저하됩니다! – RobM
@RobM 주어진 예제는 단일 프로세스를 사용하며 리소스 경합은 없습니다. – Apalala