7월, 2015의 게시물 표시

OpenCL 워크 그룹 사이즈 결정(How to determine work group size on OpenCL)

OpenCL을 사용하여 워크그룹 사이즈(CUDA에서는 Dimension, block, thread)를 결정해야 할때 Global workgorup size 는 해결하고자 하는 총 문제수를 커버 해야한다.  즉, 1024 x 1024 행렬이 있다면 커맨드큐에 NDRagneKernel을 할때 global workgroup size는 1024 x 1024 = 1048576 이 된다. Local workgorup size를 NULL 로 입력해주면 OpenCL이 알아서 실행하여 준다. 하지만 성능향상을 위해서는 local workgorup size를 수동으로 넣어주어야 할때가 있다. 연산장치(GPU 또는 기타장치)의 프로필을 보면 Max work group size 정보를 알 수 있다. 예를 들어 Max work group size 가 256 이었다면 local work group size는 모든 Dimenstion을 곱했을때 256 보다 같거나 작아야 한다. 저 256이라는 숫자는 보통 FrontWave(CUDA에서는 WARP) 에 의해서 결정되는데 Hardware 적으로 context switching 할 수 있는 총 그룹수와 PE( processing element ) 수에 의해 결정된다. PE가 64개 이고 FraoneWawe가 4이면 256이기 때문에 local workgorup 에서 처리할수 있는 work item 갯수는 256개가 된다. 총연산 유닛(compute unit)이 32개 라면 64(PE)*32(CU) = 2048 개가 동시에 처리되고 2048*4 = 8192 개 의 work-item이 스위칭되면서 실행된다.  이때 work-item들이 메모리에 동시에 접근할때 대역폭 정보 등까지 고려되어야 성능 향상에 대한 이해와 최적화를 할 수 있다.

Data dependence

Data dependence Flow Dependence(True dependence) Anti Dependence Output Dependence Flow Dependence(True dependence) 어떤코드 S1이 메모리 영역에 쓰고난 다음 어떤코드S2가 해당 위치를 읽음 S1과 S2는 동시에 실행하거나 순서를 바꿀수 없음 Anti Dependence 어떤코드 S1이 메모리 영역에서 읽고 , 그다음 어떤코드 S2가 해당 영역에 씀 S1과 S2는 동시에 실행하거나 순서를 바꿀수 없으나 S2코드를 수정하여 dependence를 제거할 수 있음 Output Dependence 어떤코드 S1이 메모리 영역에 쓰고, 그다음 어떤코드 S2가 해당 영역을 읽음 Anti Dependence와 마찬가지로 순서를 바꿀수 없으나 코드 수정으로 dependence 제거 가능 루프 캐리드 디펜던스(Loop-carried dependence) 루프 안에서 이전 이터레이션과 다음 이터레이션에 dependence가 존재 이터레이션들을 각각 동시에 실행 불가능 루프 인디펜던트 디펜던스(Loop-independent depecdence) 루프 안에 있으나 루프와 무관하게 루프안 코드들이 depecdence가 존재(Flow, anti, output 이 loop안에 있으면 loop-independent depecdence라고 하는것 같음)

C pointer #2 ( 2 Dimension, 3 Demension pointer )

int *i; int형 자료를 가르키는 포인터 i double (*a)[SIZE]; double이 SIZE개 있는 배열을 가르키는 포인터 a a++ 를 실행하면 a의 주소크기가 SIZE*8만큼 증가한다. a = (double (*)[SIZE])malloc(sizeof(double) * SIZE * SIZE); cast는 위와 같이 한다. 그럼 3차원은? double (*a)[SIZE][SIZE] = (double (*)[SIZE][SIZE]) malloc(sizeof(double) * SIZE * SIZE );

C pointer

int *(*func)(int *(*)(int *, char *), int **(*)(int **, char) ); int 포인터를 반환하는 func라는 함수 포인터 선언 이 함수의 인자 형식은 2개의 함수 포인터를 받음 첫번째 함수포인터는 int포인터를 return하고 인자로 int 포인터와 char 포인터를 받음 두번째 함수포인터는 int 2중포인터를 반환하고 인자로 이중 int포인터와 char 를 받음 질문은 댓글로 ㅎㅎ