문제

그래서 나는 이 질문이 어리석게 들린다는 것을 깨달았습니다(그렇습니다. 나는 듀얼 코어를 사용하고 있습니다). 그러나 두 개의 다른 라이브러리(Grand Central Dispatch 및 OpenMP)를 시도했고 clock()을 사용하여 라인을 포함하거나 포함하지 않고 코드 시간을 측정했습니다. 평행하면 속도는 같습니다.(기록을 위해 그들은 둘 다 자신의 병렬 형식을 사용하고 있었습니다).서로 다른 스레드에서 실행되고 있다고 보고하지만 아마도 동일한 코어에서 실행되고 있는 것일까요?확인할 수 있는 방법이 있나요?(두 라이브러리 모두 C용이므로 하위 계층에서는 불편합니다.) 이것은 매우 이상합니다.어떤 아이디어가 있나요?

도움이 되었습니까?

해결책

편집 : OP Comment에 대한 응답으로 Grand Central Dispatch에 대한 세부 사항이 추가되었습니다.

여기서 다른 답변은 일반적으로 유용하지만 질문에 대한 구체적인 답은 사용하지 말아야한다는 것입니다. clock() 타이밍을 비교합니다. clock() 스레드에 걸쳐 추가되는 CPU 시간을 측정합니다. 코어 사이에 작업을 분할하면 적어도 많은 CPU 시간을 사용합니다 (보통 스레드 오버 헤드로 인해 조금 더). Clock ()을 검색하십시오 이것 "프로세스가 멀티 스레드 인 경우 모든 개별 프로세스 스레드가 소비하는 CPU 시간이 추가됩니다."

작업이 스레드로 나뉘어져 있기 때문에 기다려야하는 전체 시간은 적습니다. 벽 시간 (벽 시계의 시간)을 사용해야합니다. OpenMP는 루틴을 제공합니다 omp_get_wtime() 그것을하기 위해. 예를 들어 다음과 같은 루틴을 취하십시오.

#include <omp.h>
#include <time.h>
#include <math.h>
#include <stdio.h>

int main(int argc, char *argv[]) {
    int i, nthreads;
    clock_t clock_timer;
    double wall_timer;
    for (nthreads = 1; nthreads <=8; nthreads++) {
        clock_timer = clock();
        wall_timer = omp_get_wtime();
        #pragma omp parallel for private(i) num_threads(nthreads)
        for (i = 0; i < 100000000; i++) cos(i);
        printf("%d threads: time on clock() = %.3f, on wall = %.3f\n", \
            nthreads, \
            (double) (clock() - clock_timer) / CLOCKS_PER_SEC, \
            omp_get_wtime() - wall_timer);
    }
}

결과는 다음과 같습니다.

1 threads: time on clock() = 0.258, on wall = 0.258
2 threads: time on clock() = 0.256, on wall = 0.129
3 threads: time on clock() = 0.255, on wall = 0.086
4 threads: time on clock() = 0.257, on wall = 0.065
5 threads: time on clock() = 0.255, on wall = 0.051
6 threads: time on clock() = 0.257, on wall = 0.044
7 threads: time on clock() = 0.255, on wall = 0.037
8 threads: time on clock() = 0.256, on wall = 0.033

당신은 그것을 볼 수 있습니다 clock() 시간은 크게 변하지 않습니다. 나는 0.254를 얻지 못한다 pragma, 따라서 OpenMP를 사용하지 않는 것보다 OpenMP를 사용하여 OpenMP를 사용하는 것이 약간 느리지 만 벽 시간은 각 스레드마다 감소합니다.

예를 들어 평행하지 않은 계산의 일부로 인해 개선이 항상 좋은 것은 아닙니다 ( Amdahl's_law) 또는 같은 기억과 싸우는 다른 스레드.

편집 : Grand Central Dispatch의 경우 GCD 참조 GCD가 사용하는 상태 gettimeofday 벽 시간 동안. 그래서 나는 새로운 코코아 앱을 만들고 applicationDidFinishLaunching 나는 넣었다 :

struct timeval t1,t2;
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
for (int iterations = 1; iterations <= 8; iterations++) {
    int stride = 1e8/iterations;
    gettimeofday(&t1,0);
    dispatch_apply(iterations, queue, ^(size_t i) { 
        for (int j = 0; j < stride; j++) cos(j); 
    });
    gettimeofday(&t2,0);
    NSLog(@"%d iterations: on wall = %.3f\n",iterations, \
                t2.tv_sec+t2.tv_usec/1e6-(t1.tv_sec+t1.tv_usec/1e6));
}

콘솔에서 다음과 같은 결과를 얻습니다.

2010-03-10 17:33:43.022 GCDClock[39741:a0f] 1 iterations: on wall = 0.254
2010-03-10 17:33:43.151 GCDClock[39741:a0f] 2 iterations: on wall = 0.127
2010-03-10 17:33:43.236 GCDClock[39741:a0f] 3 iterations: on wall = 0.085
2010-03-10 17:33:43.301 GCDClock[39741:a0f] 4 iterations: on wall = 0.064
2010-03-10 17:33:43.352 GCDClock[39741:a0f] 5 iterations: on wall = 0.051
2010-03-10 17:33:43.395 GCDClock[39741:a0f] 6 iterations: on wall = 0.043
2010-03-10 17:33:43.433 GCDClock[39741:a0f] 7 iterations: on wall = 0.038
2010-03-10 17:33:43.468 GCDClock[39741:a0f] 8 iterations: on wall = 0.034

내가 위에서 얻는 것과 거의 같습니다.

이것은 매우 고안된 예입니다. 실제로 -o0에서 최적화를 유지해야합니다. 그렇지 않으면 컴파일러는 계산을 유지하지 않고 루프를 전혀 수행하지 않는다는 것을 알게됩니다. 또한, 내가 복용하는 정수 cos 두 예제에서는 내용이 다르지만 결과에 너무 큰 영향을 미치지 않습니다. 참조 STRIDE 인력에 dispatch_apply 올바르게 수행하는 방법과 이유를 위해 iterations 광범위하게 비교할 수 있습니다 num_threads 이 경우.

편집 : Jacob의 답변에는 포함됩니다

병렬 처리 된 루프 내에서 OMP_GET_THREAD_NUM () 함수를 사용하여 작업중인 코어를 인쇄합니다.이 방법으로 두 코어에서 실행되고 있는지 확인할 수 있습니다.

정확하지 않습니다 (편집에 의해 부분적으로 고정되었습니다). 사용 omp_get_thread_num() 실제로 코드가 멀티 스레드가되도록하는 좋은 방법이지만 "어떤 코어가 작동하는지", 어떤 스레드를 보여주지 않습니다. 예를 들어 다음 코드 :

#include <omp.h>
#include <stdio.h>

int main() {
    int i;
    #pragma omp parallel for private(i) num_threads(50)
    for (i = 0; i < 50; i++) printf("%d\n", omp_get_thread_num());
}

스레드가 0-49를 사용하고 있음을 인쇄하지만 8 개의 코어 만 가지고 있기 때문에 어떤 코어가 작동하는지 보여주지 않습니다. 활동 모니터를 살펴보면 (OP가 언급 한 GCD, Mac에 있어야합니다 - GO Window/CPU Usage), 코어 사이에 작업이 전환되는 것을 볼 수 있습니다. 그래서 Core! = 스레드.

다른 팁

대부분의 실행 시간은 병렬화 된 루프에 구속되지 않을 가능성이 높습니다.

내 제안은 대부분의 시간이 걸리는 것을보기 위해 코드를 프로파일 링하는 것입니다. 대부분의 엔지니어는이 작업을 수행해야한다고 말할 것입니다. ~ 전에 사물을 최적화하기 위해 과감한 일을합니다.

세부 사항없이 추측하기가 어렵습니다. 어쩌면 응용 프로그램이 CPU 구속이 아닐 수도 있습니다. 코드가 실행되는 동안 CPU로드를 보았습니까? 적어도 하나의 코어에서 100%에 도달 했습니까?

귀하의 질문은 응용 프로그램의 특성이 무엇인지, 개선을 시도하고, 결과를 프로파일 링 (있는 경우) 등과 같은 매우 중요한 세부 사항을 놓치고 있습니다.

성능 향상 노력에 접근 할 때 몇 가지 중요한 점을 기억해야한다고 말하면서 :

  • 노력은 항상 입증 된 코드 영역에 집중해야합니다. 프로파일 링으로, 비효율적이어야합니다
  • CPU 바운드 코드를 병렬화합니다 거의 없다 성능 향상 (단일 코어 머신). 당신은 불필요한 맥락 스위치에서 귀중한 시간을 잃고 얻을 것입니다 아무것도 아님. 당신은 매우 쉽게 할 수 있습니다 악화 된 성능 이 작업을 수행함으로써.
  • 멀티 코어 머신에서 CPU 바운드 코드를 병렬화하더라도 병렬 실행을 보장하지 않는다는 것을 기억해야합니다.

교육받은 추측 (추가 세부 사항을 제외하고)은 그것이 당신이하고있는 일이라고 말할 것이기 때문에이 점에 반대하지 않도록하십시오.

루프 내에서 많은 메모리를 사용하는 경우 속도가 느려질 수 있습니다.또한 스레딩을 수동으로 처리하기 위해 pthread 라이브러리를 살펴볼 수도 있습니다.

나는 그것을 사용한다 omp_get_thread_num() 병렬 루프 내에서 작동하는 코어를 인쇄하기 위해 기능 지정하지 않는 경우 num_threads. 예를 들어,

printf("Computing bla %d on core %d/%d ...\n",i+1,omp_get_thread_num()+1,omp_get_max_threads());

위의는이 Pragma #Pragma Omp Parallel for Default (없음) 공유 (A, B, C)에 대해 작동합니다.

이렇게하면 2 개의 스레드 만 생성되므로 두 코어에서 실행되고 있는지 확인할 수 있습니다.

BTW, 컴파일 할 때 OpenMP가 활성화되어 있습니까? Visual Studio에서는 속성 페이지, C++ -> Language 그리고 설정 OpenMP Support 에게 Yes

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top