2013-09-03 4 views
0

나는 약 numpy 배열이 n입니다. 전역 ID가 i 인 OpenCL 작업자는 각 배열의 i 요소 만 봅니다. 기억을 어떻게 배열해야합니까?OpenCL 용 메모리 정렬

그래픽 카드의 배열을 인터리빙하려고했지만 작업 그룹 메모리 액세스 패턴을 이해하지 못하기 때문에 성능이 향상 될지 잘 모르겠습니다.

답변

1

내가, NumPy와 익숙하지 않다 그러나 경우 :

  • 글로벌 ID i와 스레드가 (당신이 언급 한 바와 같이)
  • 데이터 유형이 적절한 메모리 정렬을 가지고 i 번째 요소 본다 (4 , 8, 16)
  • 각 스레드가 한번에

합체는 때문에 메모리 액세스 메모리가 최적 처리량을 달성 할 수 있어야 32, 64, 128 비트를 읽는다. 이 경우 인터리빙은 성능 향상을 가져 오지 못합니다.

마지막 두 포인트 중 하나가 충족되지 않고 인터리빙을 통해 달성 할 수있는 경우 성능이 향상 될 수 있습니다.

은 편집 : 구조체 배열의 (SOA) 구조체의 배열 (의 AoS) 대를

이 점은 매우 자주 문헌에서 볼 수 있습니다. 나는 그것을 짧게 만들 것이다 :

AoS보다 SoA가 더 좋은 이유는 무엇입니까? 상상해보십시오. 32 비트 데이터 유형의 배열이 10 개 있습니다. AoS 솔루션은 다음과 같습니다.

struct Data 
{ 
    float a0; 
    float a1; 
    ... 
    float a9; 
}; // 10 x 32bit = 320 bit 

struct Data array[512]; 

메모리 읽기는 어떻게됩니까? 메모리가 병합되지 않아 메모리 전송이 병합되지 않습니다. 그러나 읽는 데 필요한 코드는 매우 짧은 : 약간의 행운과 함께

Data a = array[i]; 

컴파일러는, 적어도, 읽기 지침의 일부를 병합 할만큼 똑똑하다. 옵션은 명시적인 메모리 정렬입니다. 이렇게하면 GPU에서 매우 제한적인 전역 메모리를 사용할 수 있습니다.

이제 SOA 솔루션 :

struct Data 
{ 
    float a0[512]; 
    float a1[512]; 
    ... 
    float a9[512]; 
}; 

struct Data array; 

메모리에 액세스하는 작업은 조금 더 복잡하지만 모든 액세스가 합체 읽기에 결합 될 수 있고 더 메모리 정렬이 필요하지 않습니다. 또한 구조체를 잊어 버리고 성능 문제없이 각 배열을 그대로 사용할 수 있습니다.

사용할 수있는 또 다른 사항은 벡터화 된 데이터 유형입니다 (numpy 배열이 허용하는 경우). float2, float4 (또는 int, double ...와 같은 다른 간단한 데이터 유형)를 사용하여 결합 된 메모리 전송을 활용할 수 있습니다. 즉, float4 배열에 대한 모든 읽기는 메모리 처리량을 최대화하는 128 비트 메모리 전송으로 병합됩니다.

+0

죄송합니다. 나는 각 배열의 i 번째 요소를 봅니다. 이 요소들을 서로 가깝게 유지하려고 노력하면 안 될까요? –

+0

GPU 프로그래밍의 일반적인 가이드 라인은 어레이 구조 (Soar)의 사용이 선호한다는 것입니다. 나는 이것을 받아들이 기 위해 나의 대답을 편집 할 것이다. –

+0

예, 이것이 제가 묻는 바입니다. –