2013-05-06 3 views
3

방금 ​​레이 트레이서를 프로그래밍해야했던 컴퓨터 그래픽 코스를 완료했습니다. 모든 결과가 정확했지만 OpenMP 사용에 대해 혼란스러워했습니다. BTW는 과정에 포함되지 않았습니다. 나는이 루프를 가지고있다. (C++) :최적화 과정에서 혼란 스럽습니다

#pragma omp parallel for private(L, ray) 
// for (x = x_from; x < x_till; x++) { 
// printf("Col: %5d\n", x); 
// for (y = y_from; y < y_till; y++) { 
    for (int xy = 0; xy < xy_range; xy++) { 
    int x = x_from + (xy % x_width); 
    int y = y_from + (xy/x_width); 
     ray = cam->get_ray_at(x, y); 
     L = trace_ray(ray, 0, cam->inter); 
    #pragma omp critical 
    cam->set_pixel(x, y, L); 
    } 
// } 
} 

많은 구성을 시도했다. 하지만 결국 가장 혼란스럽게 생각하는 것은 위의 버전이 결합 된 단일 버전을 사용하는 것이 가장 효율적이라는 것입니다 (x와 y를 구분하는 데 150 초와 120 초를 사용하는 것입니다. '중요'는 타이밍을 눈에 띄게 변경하지 않습니다.)

기타 : 하나의 for 루프가 각각의 반복을 병렬 처리 할 것을 기대하지만이 방법을 사용하면 25 개의 루프가 8-8-8-1 (8 코어)의 그룹으로 실행됩니다. 'for for'를 'parallel for'에서 제거하면 이 약간 개선됨 (148 대 150s)

또한 로컬과 로컬을 비교해 보았습니다. 정의 (필요한 private pragma로). 루프 내에서 L과 ray를 선언하려고 시도했다.

Single loop    Yes      No      No      Yes  
'Critical"    No      No      Yes      Yes 
       ---------------------- ---------------------- ---------------------- ---------------------- 
       User CPU  Mean User CPU  Mean User CPU  Mean User CPU  Mean 
Scene 5   37.9 158.9 3.66 26.5 185.5 7.00 27.0 187.7 6.95 38.7 161.8 4.18 
Scene 6   18.8 110  5.85 17.7 112  6.32 18.1 113.8 5.29 19.4 112.2 5.78 
Scene 7   149  658.8 4.42 114  679.9 5.96 114  653.8 5.73 149  659.8 4.43 
Plane   112.0 497.3 4.44 105  520.5 4.95 103.8 525  5.06 113.5 504.8 4.45  
5-balls   126  760.2 6.03 162.3 697.5 4.36 170.3 725.3 4.23 127.3 766.5 6.02 

은 '평균'평균 핵심 직업이다 CPU/사용자입니다 ... 여기

내가 제안이나 포인터를 감사하겠습니다은 ... 좀 더 정확한 데이터입니다. 여러 경우에 평균은 4.xx입니다.

솔루션 및 결과

이 우수한 결과가 다음과 같이 라인 로의 #pragma OMP 평행 일정 (동적, 1) 가산하여 얻어진
Single loop    Yes      No 
       ---------------------- ---------------------- 
       User CPU  Mean User CPU  Mean 
Scene 5   23.9 190.1 7.95 24.4 190.7 7.82 
Scene 6   14.3 114.2 7.98 14.5 114.9 7.92 
Scene 7   85.5 675.9 7.91 106.9 698.8 6.54 
Plane   72.7 579.1 7.97 72.6 578.4 7.97 
5-balls   104.8 823.3 7.86 103.9 825.1 7.94 

: 참조

#pragma omp parallel for schedule(dynamic, 1) 

을 (컴파일 시간이 인 것과 대조적으로) 코어의 런타임로드 분포에 이르기까지 다양합니다.

', 1'매개 변수는 청크의 크기를 제한하는 것입니다. 빠져있을 수 있습니다.이 경우 openmp는 기본값 인 을 사용합니다. 어쩌면 1을 더하면 부하 분산이 너무 세밀하게 이루어지기 때문에 이지만 성능 차이는 찾을 수 없습니다. raytracing 작업이 너무 느리고 관리 오버 헤드가 전혀 표시되지 않는 것으로 짐작합니다.

+0

당신은 아마 "에 대한 별도의 x와 y에 대한 120S 대 150초"에 의해 당신이 무슨 뜻인지 몇 가지 코드 예제를 추가 할 수 있습니다 .... "사실 별도의에게에서 y-loops (목록에 주석 처리되어 있음)는로드를보다 효율적으로 배포하는 것처럼 보입니다. "...." 'for for'는 'parallel for'에서 제거하면 약간 향상됩니까? –

+0

코드는 위와 동일하며 xy-for (및 x/y 구분 기호)에 대해 별도로 주석 처리되지 않고 주석 처리되지 않았습니다. 별도의 for-loops는 나머지는 모두 동일하게 실행 시간을 120 초로 지정합니다. 단 하나는 150s에 간다. – jcoppens

답변

3

OpenCL에서 전체 광선 트리 (반사 및 굴절)에서 작동하는 Whitt 광선 광선 추적기를 작성했습니다. 아직 OpenMP로 해본 적이 없지만 그게 내 목표입니다. OpenMP를 배우고 싶다면 좀 더 간단한 작업부터 시작해야합니다. 하지만 몇 가지 의견을 내 보자.

시간은 어떻게 지내십니까? 당신은 "for for '를'parallel for '에서'제거하는 것이 약간 향상됩니다 '라고 썼습니다. 그건 말이 안돼. for를 제거하면 각 스레드에서 동일한 코드를 실행하여 트레드를 다른 반복에 배포하지 않습니다 (이를 보여주기 위해 몇 가지 세계 테스트를 수행하십시오). 더 빠르지 않아야합니다. 그게 당신이 타이밍을 어떻게하는지 궁금합니다. 타이밍을 수행하는 방법을 보여주기 위해 몇 가지 코드를 추가했습니다.

critical을 사용할 필요가 없습니다. 각 반복이 다른 픽셀에 쓰는 경우 필요하지 않습니다. 장면의 복잡성에 따라 critical은 훨씬 느려질 수 있습니다.

마지막으로 최상의 성능을 얻으려면 SSE/AVX도 사용하고 여러 픽셀을 한꺼번에 조작하고 싶을 것입니다. 이는 패킷 기반 레이 트레이싱이라고 불리는 것을 통해 수행 될 수 있습니다. 이것에 대한 좋은 토론을 보려면 다음 링크를 참조하십시오 http://graphics.stanford.edu/~boulos/papers/cook_gi07.pdf

편집 : 각 픽셀은 일정 (동적 인)보다는 일정한 (정적) 일정한 (일반적으로는 아니지만) 기본값을 사용하려고하기 때문에. 코드를 참조하십시오.

잉고 월드의 박사 학위 논문 : http://www.sci.utah.edu/~wald/PhD/

double dtime = omp_get_wtime(); 
#pragma omp parallel 
{ 
    Ray ray; 
    Color L; 
    #pragma omp for schedule(dynamic) 
    for (int xy = 0; xy < xy_range; xy++) { 
     int x = x_from + (xy % x_width); 
     int y = y_from + (xy/x_width); 
     ray = cam->get_ray_at(x, y); 
     L = trace_ray(ray, 0, cam->inter); 
     cam->set_pixel(x, y, L); 
    } 
} 
dtime = omp_get_wtime() - dtime; 
printf("time %f\n", dtime); 
+0

안녕하세요 렉스맨 ... 답변 주셔서 감사합니다. 내가 측정하는 시간이 비교적 길기 때문에 수십 또는 수십 초 정도의 시간이 걸리므로 프로그램 설정을 무시할 수 있다고 생각하고 단순히 프로그램 실행 시간을 '시간'(프로그램 자체 외부)으로 설정하십시오. openMP 자체의 문제를 피할 수 있다고 생각했습니다. 랜덤 오류 픽셀에 몇 가지 문제가 있었기 때문에 비판적인 내용을 추가했습니다. 나는 또한 'critical'을 제거하려고 시도했다. 그리고 타이밍은 기본적으로 동일했다. 왜냐하면 배열 할당 시간이 다시 매우 짧기 때문이다. – jcoppens

+0

잘못된 픽셀을 얻는다면 성능이 저하되는 경쟁 조건이 있음을 나에게 알리는 중요성이 필요합니다. "set_pixel (x, y, L)"이 x, y의 서로 다른 값에 대해 동일한 픽셀에 적용될 수 있습니까? L은 정확히 무엇입니까? –

+0

문제는 set_pixel이 픽셀을 잘못된 위치에 썼다는 것입니다. 가치는 옳았고 다른 (올바른) 위치에서 누락되었습니다. 이상하게도이 문제는 더 이상 발생하지 않습니다 (테스트 할 것입니다). 제가 알아 차린 이상한 것들 중 하나는 렌더링이 끝나기 전에 사용량이 8 코어에서 3 코어로 떨어지는 것입니다. 장면은 기본적으로 일정한 복잡성입니다. 실제 병목 현상은 없습니다. 그래서 이런 일은 일어나지 않아야합니다. – jcoppens