2011-12-29 1 views
5

valgrind를 사용하여 멀티 스레드 소켓 프로그램을 실행하고 있습니다. 클라이언트는 TCP를 통해 서버에 요청을 보낸 다음 부울을 기다리며 대기합니다. 부울은 서버의 응답을 처리하는 콜백 함수가 호출 될 때 설정됩니다. 응답이 수신되면 (그리고 부울 플래그가 설정된 경우) 서버는 다시 요청을 보내고 반복적으로 반복합니다.멀티 스레드 소켓 프로그램에서 valgrind가 멈 춥니 다

공유 변수 (부울)에 대한 액세스 권한이 없으면 스레딩 문제가 발생할 수 있지만 pthread 뮤텍스를 사용해 보았습니다. 프로그램이 약 20 % 속도가 느려집니다 (속도가 중요합니다). 단일 주기로 수행 할 수 있기 때문에 공유 부울 변수에 쓰는 것이 좋다고 확신합니다.

프로그램이 valgrind 외부에서 정상적으로 실행되지만 valgrind를 사용하여 실행하면 프로그램이 멈추는 경우가 많습니다. 나는 프로그램을 밤새껏 운영하기 위해 남겨 뒀다 .. 보통 그것은 완료하는 데 몇 초가 걸린다. 그래서 나는 그것이 프로그램을 끝내기에 충분히 오랫동안 기다리지 않는 경우라고 생각하지 않는다. 스레딩은 오픈 소스 엔진 프레임 워크 (빠른 수정)에서 관리하므로 스레드 작성/관리 방법에 문제가 있다고 생각하지 않습니다.

누가 멀티 스레드 프로그램/바쁜 대기 루프/소켓 통신 (또는 이들의 조합) 주위에 valgrind와 어떤 문제를 알고 있습니까?

+1

공유 부울 변수에서 busy-waiting은 "하나의 주기로 완료"되지 않습니다. 루프 반복마다 여러 주기로 이루어지며, 네트워크에서 TCP 왕복으로 대기중인 경우 루프는 수십억 번 반복 될 가능성이 있습니다 (따라서 다른 곳에서 더 잘 사용되었을 수있는 수십억 개의 CPU 사이클을 낭비합니다). 언급 한 것 중 하나보다 나은 솔루션은 조건 변수를 기다리는 것이고, 콜백 함수가 데이터가 준비되면 스레드를 깨우기 위해 조건 변수에 신호를 보내도록하는 것입니다. –

+0

나는 부울 변수에 대한 쓰기가 하나의주기 (전체 대기 중 대기 프로세스가 아님)로 완료되었다고 말했습니다. 즉, 부울 변수에 대한 쓰기가 원자 적으로 수행되어야한다고 말했을 것입니다 (캐시 미스 (cache miss) 등이 단일 CPU주기를 지나서 단일 바이트의 쓰기를 푸시 할 수 있음) – Taras

+0

Jeremy가 말한 바 - busy wait는 나쁜 생각입니다. 더 느리고 느릴 가능성은 희박합니다. – BillT

답변

6

다른 답변은 표준 동기화 접근법 (내가 완전히 동의 한 것)을 주장하지만, 대신 Valgrind에 관한 귀하의 질문에 대답해야한다고 생각합니다.

내가 아는 한 Valgrind는 멀티 스레드 환경에서 실행하는 데 문제가 없습니다. Valgrind가 응용 프로그램을 단일 코어에서 실행하도록 강요하지만, 그 이외에는 스레드에 영향을 미치지 않아야합니다.

Valgrind가 응용 프로그램에서 주로 수행하는 작업은 독립 실행 형 응용 프로그램을 실행하는 동안 일반적으로 볼 수없는 코드의 버그 및 경쟁 조건을 노출하는 방식으로 스레드 간의 타이밍 및 상호 작용을 변경하는 것입니다.

당신이 사용하고있는 오픈 소스 스레딩 프레임 워크에 버그가 없다는 것을 결정하기 위해 적용한 동일한 논리가 제 생각에는 Valgrind에도 적용됩니다. 코드에서 이러한 중단을 버그로 간주하고 디버깅하는 것이 가장 가능성이 높기 때문에이 버그를 디버그하는 것이 좋습니다.

뮤텍스를 사용하면 설명 된 문제가 과도하게 발생합니다. 대신 세마포 또는 조건 변수를 조사해야합니다.

행운을 빈다.

+0

내 코드에 버그가 있다는 것을 완전히 확신하지는 않지만 게시는주의해야합니다. 사이드 노트 - pthread 라이브러리를 사용하여 조건 변수를 살펴 보았습니다. 실제 조건 자체에서 경쟁 조건을 정지 시키려면 뮤텍스가 필요합니다. – Taras

+1

@Taras : 조건 변수에서 정확합니다. 이 경우에는 세마포어가 선호됩니다. 뮤텍스보다 훨씬 가볍습니다. 멈춤 문제에 관해, gdb가 무엇을하고 있는지 알아보기 위해 걸려있는 프로세스를 검사 해 보시지 않겠습니까? – Miguel

3

부울 값 읽기/쓰기는 x86에서 원자 연산이 아닙니다. Is volatile a proper way to make a single byte atomic in C/C++?이 부울을 작성하는 원자 작동하더라도

+0

대부분의 쓰는 경우 부울은 원자 적입니다. "CPU는 일반적으로 단일 바이트를 읽고 원자 적으로 쓰는 중입니다." 질문의 대답에서 문제는 원 자성이 아닙니다. 모든 CPU가 새로운 값을 볼 때입니다. – Taras

2

, 다른 메모리 주위의 compiler and the CPU are free to re-order the update가 액세스 :

여기 내 질문을 참조하십시오. 바쁜 대기 스레드가 통화 중 루프에서 깨어나서 이 아니고이 실제로 업데이트 된 것을 발견했습니다.

일관된 프로그램을 쓸 때마다 사용할 수있는 스레딩 프리미티브를 사용하는 것이 좋습니다.

+0

두 스레드간에 공유되는 유일한 것은 부울 플래그 (신호로 사용됨)입니다. busy 대기 스레드는 플래그가 설정되어있는 경우에만 깨우기 만합니다. 이는 플래그의 변경 사항이 busy 대기중인 스레드를 실행중인 CPU로 전달되어야 함을 의미합니다. 이 경우, 설명 된 코드가 여전히 올바르게 작동하지 않습니까? – Taras

+0

ㅎ, 아직 신호를 보내셨습니까? 그 트릭을 할 수도 있습니다. :) – sarnold