Notice
Recent Posts
Recent Comments
Link
반응형
«   2026/01   »
1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31
Archives
Today
Total
관리 메뉴

RenderLog

VGPR, SGPR 사용여부 확인 본문

Graphics/Graphics

VGPR, SGPR 사용여부 확인

scahp 2020. 9. 24. 01:35

 

GPU에 대해서 더 공부하고 싶은 차에 [번역] INTRO TO GPU SCALARIZATION – PART 1 글을 봤었고, SGPR/SALU를 사용하는 경우 Wave내에 모든 Thread가 동일한 코드를 사용하게 되어서 성능 향상이 있을 것이라고 했습니다.

 

 

사실 이쪽은 완전히 새로운 영역이라... 성능차이가 정말 나는 것인가? 한 번해보고 싶었는데, 현재 Shader 코드가 VGPR/VALU or SGPR/SALU를 사용하는지 여부도 확인하는 법을 몰랐습니다. 최근에 렌더독을 이용하면 이 것을 확인 할 수 있다는 것을 알게 되었고, 실제로 Shader 코드가 사용하는 레지스터를 판별 할 수 있는지 한번 테스트 해봤습니다.

 

[번역] INTRO TO GPU SCALARIZATION – PART 1에서는 Note[0]에 SALU에는 ISA에 부동소수점 연산 명령어가 없어서 VALU가 될 거라고 하던데, 실제 AMD "Vega" Instruction Set Architecture에 나와있는 것을 확인했습니다.

 

출처 : https://developer.amd.com/wp-content/resources/Vega_Shader_ISA.pdf#page35

 

 

그리고 렌더독으로 쉐이더 코드를 테스트 해본 결과 float인 경우 SGPR의 데이터를 VGPR에 올린 뒤 VALU로 연산되는 것을 아래 코드로 확인할 수 있습니다. 렌더독에서 Disassembly type을 Vega20으로 하여 디버깅 한 예 입니다.

 

 

//////////////////////////////////////////////////////////////////////////////////	
// 아래 코드가 주석대로 SGPR과 VGPR에 올라가는지 확인 해보자.
//
// This will be in a SGPR
// -> [OK 잘 올라감]
float s_value = LightDirection.x;

// This will be put in VGPRs via a VMEM load as pixelCoord is in VGPRs
// -> [VGPR에 잘 올라감]
float4 v_textureSample = ShaderTextures[0].Sample(SamplerType, Input.Tex);

// This will be put in SGPRs via a SMEM load as 0 is constant.
// -> [SGPR에 잘 올라감]
TestInput s_someData = TestStructuredBuffer.Load(0);

// This should be an SALU op (output in SGPR) since both operands are in SGPRs
// (Note, check note [0])
// -> [여기서 SALU가 사용될 것이라고 했지만 아니었음. SGPR에는 32bit Integer와 
//     32 bit or 64 bit Bit연산만 지원해서 VGPR로 옮긴 뒤 VALU로 연산함]
// * s_someData.Color.x 는 float임 *
float s_someModifier = s_value + s_someData.Color.x;

//// This will be a VALU (output in VGPR) since one operand is VGPR.
// -> [VGPR에 잘 올라감]
float4 v_finalResult = s_someModifier * v_textureSample;

return v_finalResult;
//////////////////////////////////////////////////////////////////////////////////	


; Disassembly for GCN (Vega 20)

; -------- Statistics ---------------------
; SGPRs: 27 out of 104 used
; VGPRs: 5 out of 256 used
; LDS: 0 out of 65536 bytes used
; 0 bytes scratch space used
; Instructions: 12 ALU, 3 Control Flow, 1 TFETCH

; -------- Disassembly --------------------
; ****** 각 어셈블리 라인의 우측에 HLSL 코드의 실제 라인을 써뒀으니 참고. ******
shader main
  asic(GFX9)
  type(PS)
                                                            // s_ps_state in s0

  s_mov_b32     m0, s24                                 // 000000000000: BEFC0018
  s_mov_b64     s[2:3], exec                            // 000000000004: BE82017E
  s_wqm_b64     exec, exec                              // 000000000008: BEFE077E               // 여기서 float4 v_textureSample = ShaderTextures[0].Sample(SamplerType, Input.Tex);
  v_interp_p1_f32  v2, v0, attr0.x                      // 00000000000C: D4080000               //
  v_interp_p1_f32  v3, v0, attr0.y                      // 000000000010: D40C0100               //
  v_interp_p2_f32  v2, v1, attr0.x                      // 000000000014: D4090001               // 이까지
  v_interp_p2_f32  v3, v1, attr0.y                      // 000000000018: D40D0101
  image_sample  v[0:3], v[2:4], s[4:11], s[16:19] dmask:0xf // 00000000001C: F0800F00 00810002
  s_buffer_load_dword  s0, s[20:23], 0x10               // 000000000024: C022000A 00000010      // float s_value = LightDirection.x;
  s_buffer_load_dword  s1, s[12:15], 0x00               // 00000000002C: C0220046 00000000      // TestInput s_someData = TestStructuredBuffer.Load(0);
  s_waitcnt     lgkmcnt(0)                              // 000000000034: BF8CC07F
  v_mov_b32     v4, s0                                  // 000000000038: 7E080200               // float s_value = LightDirection.x;
  v_add_f32     v4, s1, v4                              // 00000000003C: 02080801               // float s_someModifier = s_value + s_someData.Color.x;
  s_waitcnt     vmcnt(0)                                // 000000000040: BF8C0F70
  v_mul_f32     v0, v4, v0                              // 000000000044: 0A000104               // 여기서 float4 v_finalResult = s_someModifier * v_textureSample;
  v_mul_f32     v1, v4, v1                              // 000000000048: 0A020304               //
  v_mul_f32     v2, v4, v2                              // 00000000004C: 0A040504               //
  v_mul_f32     v3, v4, v3                              // 000000000050: 0A060704               // 이까지
  s_mov_b64     exec, s[2:3]                            // 000000000054: BEFE0102
  v_cvt_pkrtz_f16_f32  v0, v0, v1                       // 000000000058: D2960000 00020300
  v_cvt_pkrtz_f16_f32  v1, v2, v3                       // 000000000060: D2960001 00020702
  exp           mrt0, v0, v0, v1, v1 done compr vm      // 000000000068: C4001C0F 00000100      // return v_finalResult;
  s_endpgm                                              // 000000000070: BF810000
end


 

그 외에 더 다양한 툴을 프로파일링에 사용할 수 있는데, 대부분 DX12나 Vulkan에서 사용가능한 것 같네요. 특히, DX12 부터는 Wave intrinsics의 사용이 가능합니다. [번역] INTRO TO GPU SCALARIZATION – PART 1 에서 설명하는 나머지 부분은 API를 숙지하고 다시 해봐야겠네요.

 

 

추가

StructuredBuffer에 int를 전달하여 SGPR로 ALU연산이 되는지 한번 확인해봤는데, 실제로 그렇게 됩니다.

/////////////////////////////////////////////////////////////    
TestInput s_someData = TestStructuredBuffer.Load(0);
int k = s_someData.Color * s_someData.Color * 2.0;
     
return k;
/////////////////////////////////////////////////////////////

; Disassembly for GCN (Vega 20)

; -------- Statistics ---------------------
; SGPRs: 11 out of 104 used
; VGPRs: 3 out of 256 used
; LDS: 0 out of 65536 bytes used
; 0 bytes scratch space used
; Instructions: 2 ALU, 2 Control Flow, 0 TFETCH

; -------- Disassembly --------------------
shader main
  asic(GFX9)
  type(PS)
                                                            // s_ps_state in s0

  s_buffer_load_dword  s0, s[4:7], 0x00                 // 000000000000: C0220002 00000000
  s_waitcnt     lgkmcnt(0)                              // 000000000008: BF8CC07F
  s_mul_i32     s0, s0, s0                              // 00000000000C: 92000000           // int k = s_someData.Color * s_someData.Color 부분에 해당
  v_cvt_f32_i32  v0, s0 mul:2                           // 000000000010: D1450000 08000000  // 위의 결과에 2를 곱함
  v_cvt_pkrtz_f16_f32  v0, v0, v0                       // 000000000018: D2960000 00020100
  s_nop         0x0000                                  // 000000000020: BF800000
  s_nop         0x0000                                  // 000000000024: BF800000
  exp           mrt0, v0, v0, v0, v0 done compr vm      // 000000000028: C4001C0F 00000000
  s_endpgm                                              // 000000000030: BF810000
end

반응형