:) 커널 리소스를 관리하는 동안 PTX를 살펴보기로 결정했지만 이해할 수없는 몇 가지 사항이 있습니다. 여기에 내가 쓴 아주 간단한 커널은 다음과 같습니다 그럼 사용하여 컴파일 된CUDA PTX 코드 및 레지스터 메모리와의 혼동
__global__
void foo(float* out, float* in, uint32_t n)
{
uint32_t idx = blockIdx.x * blockDim.x + threadIdx.x;
uint32_t one = 5;
out[idx] = in[idx]+one;
}
: nvcc --ptxas-options=-v -keep main.cu
을 나는 콘솔에서이 출력을 가지고 :
ptxas info : 0 bytes gmem
ptxas info : Compiling entry function '_Z3fooPfS_j' for 'sm_10'
ptxas info : Used 2 registers, 36 bytes smem
을 그리고 결과 PTX는 다음과 같습니다 :
.entry _Z3fooPfS_j (
.param .u64 __cudaparm__Z3fooPfS_j_out,
.param .u64 __cudaparm__Z3fooPfS_j_in,
.param .u32 __cudaparm__Z3fooPfS_j_n)
{
.reg .u16 %rh<4>;
.reg .u32 %r<5>;
.reg .u64 %rd<8>;
.reg .f32 %f<5>;
.loc 15 17 0
$LDWbegin__Z3fooPfS_j:
.loc 15 21 0
mov.u16 %rh1, %ctaid.x;
mov.u16 %rh2, %ntid.x;
mul.wide.u16 %r1, %rh1, %rh2;
cvt.u32.u16 %r2, %tid.x;
add.u32 %r3, %r2, %r1;
cvt.u64.u32 %rd1, %r3;
mul.wide.u32 %rd2, %r3, 4;
ld.param.u64 %rd3, [__cudaparm__Z3fooPfS_j_in];
add.u64 %rd4, %rd3, %rd2;
ld.global.f32 %f1, [%rd4+0];
mov.f32 %f2, 0f40a00000; // 5
add.f32 %f3, %f1, %f2;
ld.param.u64 %rd5, [__cudaparm__Z3fooPfS_j_out];
add.u64 %rd6, %rd5, %rd2;
st.global.f32 [%rd6+0], %f3;
.loc 15 22 0
exit;
$LDWend__Z3fooPfS_j:
} // _Z3fooPfS_j
이제는 이해할 수없는 몇 가지 사항이 있습니다.
- ptx 어셈블리에 따르면 4 + 5 + 8 + 5 = 22 레지스터가 사용됩니다. 그렇다면 컴파일 중에 왜
used 2 registers
이라고 표시됩니까? - 어셈블리를 살펴보면 threadId, blockId 등의 데이터 유형이 임을 깨달았습니다. 이것이 CUDA 사양에 정의되어 있습니까? 또는이 버전은 CUDA 드라이버 버전마다 다를 수 있습니다.
- 누군가 내게이 줄을 설명해 줄 수 있습니까?
mul.wide.u16 %r1, %rh1, %rh2;
?%r1
이u32
인 이유는u32
대신wide
이 사용됩니까? - 레지스터 이름은 어떻게 선택합니까? 내 꽃병에 나는
%r
부분을 이해하지만h
(null),d
부분을 이해하지 못합니다. 데이터 유형 길이에 따라 선택됩니까? 즉 : 16 비트의 경우h
, 32 비트의 경우 null, 64 비트의 경우d
? - 커널의 마지막 2 줄을
out[idx] = in[idx];
으로 바꾼다면 프로그램을 컴파일 할 때 3 개의 레지스터가 사용된다고 말합니다! 지금 더 많은 레지스터를 어떻게 사용할 수 있습니까?
내 테스트 커널이 배열 인덱스가 범위를 벗어 났는지 확인하지 않는다는 사실을 무시하십시오.
대단히 감사합니다.
(1) PTXAS는 PTX를 기계어로 변환하는 컴파일러 구성 요소입니다. 따라서 -Xptxas -v의 레지스터 수는 기계 코드에 사용 된 물리 레지스터에 해당합니다 (cuobjdump --dump-sass로 검사 할 수 있음). PTX는 가상 레지스터를 사용하는 중간 언어입니다. PTX 코드는 SSA (단일 정적 할당) 형식으로 생성되기 때문에 작성된 모든 새로운 결과에는 새로운 가상 레지스터 번호가 할당됩니다. (2) mul.wide는 PTX 사양 (CUDA 설명서의 일부 임)에 설명되어 있습니다. 이 경우 두 개의 u16 피연산자를 곱하여 u32 결과를 얻습니다 (즉, 전체 제품) – njuffa