2012-06-21 7 views
4

나는 자체 맵을 사용하여 데이터를 저장하는 C++ 프로젝트에서 작업하고있다.이 의미에서 맵은 "지리 정보"맵, 즉 이미지와 비슷할 것이다. 거기에서 읽고 쓰는 다른 스레드가 있습니다. 지도의 데이터는 정수 벡터의 표준 벡터에 저장됩니다. 크기는 변경되지 않고 getter 및 setter 기능을 통해 특정 픽셀의 내용 만 변경됩니다.multithread vector

내 문제는 다음과 같습니다. 때로는 모든 것이 잘 작동하지만 더 자주 픽셀 값이 부호가 바뀌거나 완전히 달라져야한다는 의미에서 모든 이미지가 손상됩니다. 이것이 픽셀에 대한 스레드 읽기/쓰기 액세스의 문제 일 수 있습니까? 그렇다면 표준 벡터 대신에 무엇을 사용해야합니까? 뮤텍스를 사용하여 하나의 스레드 만 벡터에 읽거나 쓰도록 시도했지만 이러한 읽기/쓰기 작업은 너무 자주 발생하므로 모든 작업에서 벡터를 잠그면 응용 프로그램이 너무 느려지 게됩니다.

+0

1D 벡터를 사용해야합니다. 2D보다 뛰어납니다. – chris

+1

원자 조작은 "크기가 변하지 않고 getter 및 setter 함수를 통해 특정 픽셀의 내용 만"라고 말하는 방식을 통해이 트릭을 수행 할 수 있습니다. 또한 캐시 중독을 최소화하기 위해 액세스를 '분할'(즉, 서로 다른 스레드가 정확히 동일한 픽셀을 수정하지 못하게)하십시오. 물론 두 개의 인접한 픽셀이 서로 일치한다는 것을 보장하지 않지만, 혼돈 된 방식으로 수정하면 잠금이 다시 보장되지 않습니다. 그러나 이는 보증합니다. 동시에 증가하고 감소하는 값은 "이상한"결과를 얻지 못합니다. – Damon

+0

@Damon : C++ 11에 정의 된 메모리 모델은 인접한 픽셀로 설명하는 효과가 발생하지 않도록하기위한 것입니다. [here] (http://stackoverflow.com/questions/6319146/)를 참조하십시오. –

답변

6

어떤 종류의 잠금 장치가 필요합니다. 성능이 너무 나빠지는 것을 막으려면 잠금 장치의 범위를 가능한 작게 만들어야합니다. 예를 들어, 개별 행 벡터를 잠글 수 있기 때문에 서로 다른 행의 쓰기가 서로 간섭하지 않습니다. 어떤 유형의 솔루션이 가장 적합한 지 액세스 패턴과 플랫폼에 따라 다릅니다.

+0

고마워. 필자는 필자의 벡터의 작은 부분 만 잠글려고 노력할 것이다. 나는 그것을 읽기 작업자에게도 고정시켜야 할 것인가? –

+0

이것은 데이터로 무엇을하고 싶은지에 따라 다릅니다. 읽는 경우에만 자물쇠가 필요하지 않습니다. 쓰고있는 지역을 읽으려면 자물쇠가 있어야하지만 [독자 - 작성자 잠금] (http://en.wikipedia.org/wiki/Readers-writer_lock)을 사용할 수 있습니다. 어쩌면 하나의 작가 만 있다면 자물쇠없이 살 수도 있습니다. 때때로 일관성없는 데이터를 읽을 수도 있지만, 그 일을하는 것에 따라 문제가 될 수도 있고 없을 수도 있습니다. –

0

멀티 스레딩을 할 때 가능한 한 스레드 범위를 분리하십시오.

고려 및 예. 벽을 가지고 흑백 줄무늬로 페인트하고 싶다고 상상해보십시오. 그리고 작업 속도를 높이기 위해 두 명의 직원을 고용하기로 결정했습니다.

이제이 작업을 두 가지 방식으로 할당 할 수 있습니다. 1. 검은 색 줄무늬를 한 작업자에게 지정하고 흰색을 다른 작업자에게 지정합니다. 2. 벽을 두 개의 파티션으로 나누고 한 파티션에 왼쪽 파티션을 할당하고 두 번째 작업자에게 오른쪽 파티션을 할당하십시오.

이제 어느 것이 더 나은 성능을 낼 수 있습니까?

일반적으로 두 번째 작업은 작업 영역이 잘 분리되어 있고 다른 작업이 자신의 작업을 기다릴 필요가 없기 때문에 두 번째 작업이 더 좋습니다. 물론 첫 번째 접근법은 잘못이 아니지만 한 사람이 어떤 장소에서 그림을 그리는 것이 가능하고 두 번째 사람도 같은 장소에 도달 할 수 있으므로 첫 번째 작업이 완료 될 때까지 기다려야합니다. 이제 각각 10 명의 작업자가 하나의 특정 색만 칠하는 경우 어떻게 될지 상상해보십시오.

다중 스레드 프로그래밍은 비슷합니다. 문제 데이터를보다 나은 방법으로 분할 할 수 있다면 스레드를 효과적으로 작동하게 만들 수 있습니다.

+0

불행히도 대부분의 스레드의 경우에는 이것이 불가능합니다. 벡터의 동일한 부분에서 항상 두 개의 스레드가 작동합니다. 이 스레드 그룹은 대부분 고립되어 있습니다. –

0
  1. 경량 잠금 장치를 사용하십시오. 그건 윈도우에서 "CriticalSection"을 사용하는 것입니다. 또는 예를 들어 사용자 공간 잠금을 작성하십시오. TinyThread (http://tinythreadpp.bitsnbites.eu/)에서와 같이. 이것들은 ASM으로 작성되고 실제로 잠금과 잠금 해제에 거의 제로가되어야합니다.

  2. 잠금 장치 자체가 빠르다고 확신되면 잠금 경합이 있기 때문에 상황이 여전히 느리게 실행되는 경우입니다. 예 : 여러 개의 스레드가 모두 동일한 리소스를 잠글 필요가 있습니다. 사용 사례에서 '읽기/쓰기'뮤텍스와 같은 것을 고려하십시오. 이것은 읽기 뮤텍스와 쓰기 뮤텍스를 갖는 클래스입니다. 뮤텍스의 "readLock"메서드는 뮤텍스의 참조 카운트를 증가시키기 위해 몇 번의 사이클 만 잠급니다. "readUnlock"은 참조 횟수를 감소시킵니다. "writeLock"은 읽기 뮤텍스를 잠그고 읽기 뮤텍스를 잠그지 않도록하는 플래그를 설정합니다. 그런 다음 쓰기 뮤텍스를 잠그고 쓰기 작업을 수행합니다.따라서 한 번에 하나의 쓰기 작업 만 수행 할 수 있으며 쓰기 작업도 수행 할 수 없습니다. 그러나 동시 읽기는 허용됩니다.

+0

두 번째 옵션은 읽기/쓰기 잠금과 비슷하게 들릴 수 있지만 한 번의 쓰기로 여러 개의 동시 읽기를 동시에 가질 수 있습니다. http://en.wikipedia.org/wiki/Read/write_lock_pattern – Brady

+0

예. 그것이 바로 그 것이다. 읽기/쓰기 뮤텍스라고 부르는 것이 잘못 되었습니까? 모든 쓰기 작업은 상호 배타적입니다. –

+0

나는 그것의 잘못을 말하지 않겠지 만, 더 일반적으로 읽기/쓰기 잠금이라고합니다. – Brady