2012-01-07 2 views
1

대형 고정 된 개체 (예 : 고정 된 개체)에 대해 병렬 계산을 수행한다고 가정합니다. 고정 된 거대한 스파 스 (지시 된) 그래프 또는 이와 유사한 종류의 개체.OpenCL : JOCL에서 로컬 메모리를 사용하는 방법

그래프에서 랜덤 워크 (walk)와 같이이 그래프 또는 객체에 대한 합리적인 계산을 수행하려면 그래프를 전역 메모리에 두는 것이 속도면에서 바람직하지 않을 수 있습니다.

로컬/개인용 메모리를 남겨 둡니다. GPU 아키텍처를 정확히 이해했다면 로컬 또는 개인 메모리의 (읽기 전용) 액세스간에 속도 차이가 거의 없습니다. 맞습니까? 그래프를 개인용 메모리로 복사하는 것을 꺼려합니다. 이는 모든 단일 작업 단위가 GPU의 메모리를 매우 빠르게 먹을 수있는 전체 그래프를 저장해야한다는 것을 의미하기 때문에 (그리고 매우 큰 그래프의 경우에는 사용하거나 OS를 불안정하게 만들 수 있음).

그래서 로컬 대 프라이빗의 읽기 속도가 위에 있다고 가정하면 실제로 어떻게해야합니까? 예를 들어 단순화를 위해 나는 물론이

computeMe(__local const int *to, __local const int *from, __global int *result) { 
    //... 
} 

같은 커널 모양을 만들 수 있습니다 (시작하고 각 방향 가장자리의 끝 저장)를 int[] from과 에 그래프를 감소하지만 난 호출해야 표시되지 않습니다 이것은 JOCL로부터 왔는데, private/local/global 수정자가 없기 때문입니다.

로컬 변수가 각 로컬 작업 그룹의 메모리에 자동으로 기록됩니까? 아니면 어떻게 작동합니까? 이 메모리 할당을 올바르게 수행하는 방법은 무엇인지 분명하지 않습니다.

답변

3

호스트의 로컬 메모리 인수 값을 전달할 수 없습니다. 호스트는 로컬 메모리를 읽고 쓸 수 없습니다. 로컬 메모리를 사용하려면 데이터를 전역으로 전달한 다음 사용하기 전에 전역에서 로컬로 복사해야합니다. 이것은 여러 번 데이터를 읽는 경우에만 유용합니다.

상수 메모리는 어떻습니까? 입력 데이터가 변경되지 않고 크기가 너무 크지 않으면 입력 데이터를 상수 메모리에 저장하면 상당한 속도 향상을 얻을 수 있습니다. 사용 가능한 상수 메모리는 일반적으로 약 16K ~ 64K입니다.

computeMe(__constant int *to, __constant int *from, __global int *result) { 
//... 
} 

편집 (참조를 추가) : 오픈 CL의 __local 메모리의 사용 예제를 들어

here를 참조하십시오.

NVidia 하드웨어의 경우 성능 세부 사항은 NVidia OpenCL best practices guide (PDF)입니다. 여기에는 메모리 유형 간의 성능 차이에 대한 더 많은 정보가 있습니다.

+0

로컬 메모리는 상수와 비슷한 속도입니까? 나는 그래프를 반복하고있어, for (edge ​​= 0; edge user1111929

+0

또한 로컬 (비공개) 메모리에 무언가를 쓸 수있는 설명을 찾을 수 없었습니다. 어떻게해야합니까? 호스트는 전역 및 const에만 쓸 수 있으며 커널은 전역 및 개인용으로 쓸 수 있습니다. 작업 그룹의 모든 작업 단위가 공유하는 메모리에 어떻게 넣을 수 있습니까? 컴퓨팅 유닛 당 32K LOCAL_MEM을 사용할 수 있습니다. 이걸 사용하지 않으려 고 바보가 될 것입니다 ... OpenCL에서이 공간에 뭔가 쓸 방법이없는가요? 또는 OpenCL은 모든 커널에서 const 변수를 private로 이동할 때 자동으로이 작업을 수행합니까? – user1111929

+0

@ user1111929 커널은 __local 메모리를 읽고 쓸 수 있습니다. 실제로 이것은 데이터가 로컬 메모리에 저장되는 유일한 방법입니다. 상수 메모리는이 초기 복사가 필요하지 않습니다. 즉, 커널의 전역 메모리와 장벽에 전역을 복사하는 데 추가 코드가 필요하지 않습니다. 저는 __local과 __constant 메모리 사이의 속도 차이에 대해서는 알지 못합니다. 그러나 그것이 비슷하다면 순수한 추측은 __global보다 빠릅니다. – prunge

1

당신은 "그래프를 전역 메모리에 두는 것은 아마도 속도상의 이유로 문제가되지 않을 것"이라고 썼습니다. - 당신은 다른 선택의 여지가 많지 않습니다. 데이터가 일반적으로 전역 메모리에 있음을 의미합니다.

(요소 형식이 적합한 경우 특수한 경우 텍스쳐로 다시 채울 수 있습니다.) 또한 nvidia의 소위 '상수'메모리는 '방송'유형의 작업에 최적화되어 모든 스레드 같은 위치에서 읽으십시오. 처음에는이 유형을 사용하지 않는 것이 좋습니다.)

좋습니다. 먼저 '글로벌 메모리'를 사용해보십시오. 로컬 메모리의 '수명'은 커널을 실행하는 동안에 만 유효합니다.동일한 데이터 요소를 두 번 이상 다시 사용하는 경우에만 사용할 수 있습니다 (명시 적으로 미리로드하는 캐시 메모리라고 생각하면됩니다).

또한 로컬 mem은 약 16-48kbytes로 제한되어 있으므로 데이터의 일부만 저장할 수 있습니다. 이러한 블록에 맞는 하위 그래프로 그래프를 분해하십시오.

표현에서 가장자리 ([]에서 [])를 고정 크기 그룹으로 분할 할 수 있습니다.

일반적인 패턴은 로컬

your_local_array [get_local_id (0) = input_global_mem [get_global_id (0)]

단계 2. 있는지 확인 모든 스레드 전역에서

단계 1. 복사본은 (로컬 쓰레드)

이제 작업 항목 (쓰레드)은 로컬 메모리에로드 된 서브 그래프에서 작동 할 수 있습니다.

기억하십시오. 로컬 mem에는 전체 그래프의 일부만 포함됩니다. 임의의 스레드에서 임의의 노드에 액세스해야하는 경우 위의 패턴을 사용할 수 없습니다.

로컬 메모리를 사용하지 않고 (전역에서 직접 읽음) 알고리즘을 사용하여 실험을 시작하고 정상적으로 작동하는지 확인하는 것이 좋습니다 (대개 도로에 놀라움이 있습니다). 나중에 로컬 mem에 저장할 데이터 부분을 식별하여 속도를 향상시킬 수 있습니다.