2016-09-27 2 views
0

가 나는 무겁게 메모리 대역폭을 준수하고 있습니다 :FPS를 개선하고 텍스처에 임의 액세스로 메모리 대역폭을 극복하는 방법은 무엇입니까? 내 가상 현실 프로그램에서

#version 320 es 
precision lowp float; 

const int n_pool = 30; 

layout(local_size_x = 8, local_size_y = 16, local_size_z = 1) in; 
layout(rgba8, binding = 0) writeonly uniform lowp image2D image; 
layout(rgba8, binding = 1) readonly uniform lowp image2DArray pool; 

uniform mat3 RT[n_pool]; // <- this is a rotation-translation matrix 

void main() { 
    uint u = gl_GlobalInvocationID.y; 
    uint v = gl_GlobalInvocationID.x; 
    vec4 Ir = imageLoad(pool, ivec3(u,v,29)); 
    float cost = 1.0/0.0; 

    for (int j = 0; j < 16; j++) { 
     float C = 0.0; 
      for (int i = 0; i < n_pool; i++) { 
       vec3 w = RT[i]*vec3(u,v,j); 
       C += length(imageLoad(pool, ivec3(w[0],w[1],i)) - Ir); 
      } 
     } 
     cost = C < cost ? C : cost; 
    } 
    imageStore(image, ivec2(u,v), vec4(cost, cost, cost, 1.0)); 
} 

당신은 내가 임의의 많은에 액세스 있다고 볼 수 TEXTURE_2D_ARRAY (폭 = 320, 높이 = 240 층 = 30). 그러나 액세스가 이 아니기 때문에 u, v에 근접하므로 랜덤입니다. 여기

내 생각은 다음과 같습니다 (? 어쩌면 RGBA - 부호없는 바이트)

  • 다른 텍스처 형식 대신 RGBA-수레.
  • 공유 메모리가 너무 작아 하나의 그레이 스케일 이미지를 저장할 수 없습니다.
  • 루프 순서가 변경됩니다. 이상하게도,이 순서는 더 빠르지 만 다른 것은 더 나은 캐싱 동작을 가져야합니다.
  • 질감을 잘 맞출 수 있도록 작업 그룹 크기를 조정하십시오.
  • 압축 된 이미지 사용 (성능 향상을주는 경우는 거의 없습니다). 그러나 이론적으로 대역폭이 도움이됩니다.

귀하의 의견은 무엇입니까?

+2

을 충족. OpenGLES 장치에서 무거운 텍스처 읽기의 목적이 무엇인지 궁금합니다. 코드의 목적에 대해 더 많은 정보를 제공하지 않으면 최적화가 다소 까다 롭습니다. – codetiger

+0

장면의 깊이 맵 (여기서는 16 개의 개별 깊이 값)을 무차별 방식으로 최적화 할 수 있습니다. 한 프레임에서 다른 프레임으로 매트릭스 변환을하면 후속 프레임의 픽셀을 일치시킬 수 있습니다 (깊이 값이 맞다고 가정). 편집 된 버전을 참조하십시오. –

+0

"brute force"와 "optimize"라는 단어는 거의 같은 문장에 속합니다. 텍스처 형식 RGBA F32는 무엇입니까? – solidpixel

답변

0

실제 문제가 있다는 것을 보여주는 데이터가 있습니까? 대역폭입니까? 그냥 가정입니까?

실제로 문제가되지 않을 수도있는 여러 가지 문제점을 볼 수 있습니다. 예를 들어 대부분의 아키텍처에 당신이 아마 바인딩을 불러오는 균일 알 수 있도록

vec3 w = RT[i]*vec3(u,v,j); 

... 당신은하지 질감이 결합하는 mat3 배열이 내부 루프 내부에로드 할 수 있습니다. 이것은 GPU 데이터 캐시에서 잘 캐쉬해야하지만 텍스쳐 포맷이 예외적으로 넓지 않다면 imageLoad()보다 훨씬 더 비싼 냄새가 나는 루프 반복마다 여전히 재 편집되고있을 것입니다 ...

fp16 또는 fp32 RGBA 텍스처 입력이 있으면 좁은 8 비트 범용 포맷이 항상 빠릅니다 (특히 고가 인 fp32). 다음의 경우

:

cost = C < cost ? C : cost; 

... 그것은 기능이 내장 min()를 사용하는 코드 생성의 측면에서 아마 더 안정적입니다.쉐이더 계산하는 종래의 픽셀 파이프 라인에서 이동

+0

대부분의 CPU에서 (그리고 저는 GPU로 생각합니다)'''A = B

+0

그렇습니다. 대부분의 컴파일러는 이것을 하나의 명령어로 변환하지만 ESSL은 내장 된 함수 라이브러리를 가지고 있습니다.이 라이브러리는 빠르며 (코드를 더 읽기 쉽게 만듭니다.) 사용하지 마십시오 ... – solidpixel

+0

그랬습니다. (다만 읽기 쉽도록). 그것은 OpenGL에서 GPU를위한 최적화와 같은 많은 시도와 오류입니다 ... 입증 된 패턴은 항상 적용 가능하지 않습니다 –

0

UPDATE 1

  • 3 배 압축 포맷을 사용

UPDATE 2

  • 5 %의 FPS
  • 증가 속도를 높이는 가져

이 단순화 된 버전에서 UPDATE 3

  • 나는 즉석에서 나는 참으로 (외부 및 내부 루프 모두에서) 많은 일시적 벡터를 만든 보이지 않았다. 루프 내에서 mat3/vec4/vec3 생성을 제거하면 속도가 2 배 빨라졌습니다. 루프에 벡터를 만드는 것이 비용이 많이 든다는 사실에 놀랐습니다.

는 지금은 실시간으로도 깊은 오전 내 목표 ... 당신은 실제로 30 * 16 텍스처 조회를하고있는

+1

벡터를 생성하는 것은 루프가 너무 짧기 때문에 해당 루프의 컨텍스트에서 비용이 많이 듭니다. 텍스처 액세스는 단일 사이클 일 가능성이 높습니다. 따라서 한 번의 추가 오버 헤드 (예 : 오른쪽 벡터 레지스터 위치로 'i'이동)도 코드 경로 길이를 두 배로 늘릴 수 있습니다 – solidpixel