2016-12-04 1 views
0

응용 프로그램의 일부 기능을 측정하는 데 걸린 시간을 확인하려고합니다. 연결된 목록을 사용하여 메모리 내 모든 시간을 기록합니다.OMP 영역 잠금

이 과정에서 나는 목록의 끝을 추적하는 전역 변수를 도입했습니다. 새 타이밍 영역을 입력하면 목록 끝에 새 레코드가 삽입됩니다. 아주 간단한 것.

그러나 추적하고 싶은 기능 중 일부는 OpenMP 영역에서 호출됩니다. 즉, 여러 번 병렬로 호출 될 가능성이 높습니다. 그리고 이것은 내가 곤란한 곳입니다.

이것은 일반적인 Pthreads를 사용하는 경우 뮤텍스의 전역 변수에 대한 액세스를 감싸고 하루로 지정합니다. 그러나 확실하지 않습니다.이 전략은 OpenMP 지역에서 호출되는 함수에서도 여전히 작동합니까? 마찬가지로, 그들은 자물쇠를 존중합니까?

예를 들어 (컴파일,하지만 난에 걸쳐 포인트를 얻을 수 있다고 생각하지 않습니다) :

Record *head; 
Record *tail; 

void start_timing(char *name) { 
    Record *r = create_record(name); 
    tail->next_record = r; 
    tail = r; 
    return r; 
} 

int foo(void) { 
    Record r = start_timing("foo"); 
    //Do something... 
    stop_timing(r); 
} 

int main(void) { 
    Record r = start_timing("main"); 
    //Do something... 
    #pragma omp parallel for... 
    for (int i = 0; i < 42; i++) { 
     foo(); 
    } 
    //Do some more... 
    stop_timing(r); 
} 

어떤 그때로 업데이트 할 것입니다 :

void start_timing(char *name) { 
    Record *r = create_record(name); 

    acquire_mutex_on_tail(); 
    tail->next_record = r; 
    tail = r; 
    release_mutex_on_tail(); 

    return r; 
} 

(사과이 명백한 해답이있는 경우 - OpenMP 프레임 워크와 멀티 스레딩 전반에 익숙하지 않습니다.)

+0

Openmp가 pthreads (일반적으로 Linux 또는 osx의 경우)를 기반으로 작성된 경우 작동해야합니다. – tim18

답변

2

관용적 인 뮤텍스 솔루션은 OpenMP 잠금을 사용합니다 :

omp_set_lock(&taillock) 
tail->next_record = r; 
tail = r; 
omp_unset_lock(&taillock) 

어딘가에 :

omp_lock_t taillock; 
omp_init_lock(&taillock); 

... 

omp_destroy_lock(&taillock); 

간단한 OpenMP의 솔루션 :

void start_timing(char *name) { 
    Record *r = create_record(name); 
    #pragma omp critical 
    { 
     tail->next_record = r; 
     tail = r; 
    } 
    return r; 
} 

소스 코드 라인에 결합 암시 글로벌 잠금을 만듭니다. 자세한 내용은 this question에 대한 답변을 참조하십시오.

실제로 Pthread 잠금을 사용하는 것은 OpenMP가 Pthreads를 기반으로하는 시나리오에서도 작동합니다.

경고 단어

성능 측정 코드에서 잠금을 사용하는 것은 위험합니다. 또한 메모리 할당은 잠금을 사용하는 것을 의미하기도합니다. 즉, start_time에는 상당한 비용이 들고 성능은 더 많은 스레드에서 더 악화됩니다. 캐시 무효화가 한 스레드가 메모리 덩어리 (레코드)를 할당 한 다음 다른 스레드가이를 수정 (꼬리 포인터)하는 것을 고려하지 않습니다.

측정하는 섹션이 초 단위 일 경우 문제가 없지만 섹션이 수백 사이클에 불과할 경우 큰 오버 헤드와 섭동을 유발할 수 있습니다.

확장 가능한 성능 추적 기능을 생성하려면 스레드 로컬 메모리를 큰 청크로 미리 할당하고 각 스레드가 로컬 부분에만 쓰도록해야합니다.

기존 측정 인프라 일부 (예 : Score-P)를 사용할 수도 있습니다.& 섭동

우선

오버 두 (링크 개념)을 구별. 오버 헤드은 추가 시간입니다. 섭동은 측정 한 것에 대한 영향을 나타냅니다. 즉, 측정없이 발생하는 것과 다른 결과를 측정합니다. 오버 헤드는 대량으로 바람직하지 않지만 섭동은 훨씬 더 나 빠진다.

그렇습니다. 값 비싼 측정 런타임 중에 타이머를 일시 중지하면 오버 헤드가 남을 수 있습니다. 그러나 멀티 스레드 컨텍스트에서는 여전히 문제가 많습니다.

  • 하나의 스레드에서 진행 속도가 느려지므로 다른 스레드가이를 기다리고 있습니다. 암시 적 장벽 중에 당신은 그 스레드와 다른 스레드의 대기 시간을 어떻게 추측합니까?
  • 일반적으로 메모리 할당은 잠겨 있으므로 측정 런타임 중에 메모리를 할당하면 메모리 할당에 의존하는 다른 스레드의 속도가 느려집니다. 메모리 풀을 사용하여 완화하려고 할 수는 있지만 처음에는 링크 된 목록을 피할 것입니다.

+0

Score-P 링크를 제공해 주셔서 감사합니다. 나는 그것을 철저히 조사해야 할 것이다! 질문 : 현재 내부 함수를 입력하기 전에 외부 함수의 타이밍을 "일시 중지"하고 내부 함수에서 복귀 할 때 재개 타이밍을 언급해야합니다. 따라서 잠금 및 malloc 내 타이밍 정보를 캡처해야합니다 지 않습니다. 잠금 및 메모리 할당 (예 : 레코드를 malloc하고 잠금 및 위치에 삽입 한 다음 타이밍을 시작할 때까지)까지 타이밍을 시작하지 않으면 성능 오버 헤드 문제가 계속 발생합니까? – tonysdg

+0

내 마지막 단락을 참조하십시오. – Zulan

+0

Amazimg 대답. 정말 고맙습니다! – tonysdg