이 질문은 Mystical의 조언에 따라 여기 내 질문에 계속됩니다.
내 질문에 계속해서 스칼라 명령어 대신 포장 명령어를 사용하면 내장 함수를 사용하는 코드가 매우 유사하게 보입니다.
for(int i=0; i<size; i+=16) {
y1 = _mm_load_ps(output[i]);
…
y4 = _mm_load_ps(output[i+12]);
for(k=0; k<ksize; k++){
for(l=0; l<ksize; l++){
w = _mm_set_ps1(weight[i+k+l]);
x1 = _mm_load_ps(input[i+k+l]);
y1 = _mm_add_ps(y1,_mm_mul_ps(w,x1));
…
x4 = _mm_load_ps(input[i+k+l+12]);
y4 = _mm_add_ps(y4,_mm_mul_ps(w,x4));
}
}
_mm_store_ps(&output[i],y1);
…
_mm_store_ps(&output[i+12],y4);
}
이 커널의 측정 된 성능은주기 당 약 5.6FP 작업이지만 스칼라 버전 성능의 정확히 4 배, 즉주기 당 4.1,6 = 6,4 FP 작업이 될 것으로 예상합니다.
가중치 요소의 이동을 고려하면 (이를 지적 해 주셔서 감사합니다) 일정은 다음과 같습니다.
movss
스칼라 가중치 값을 XMM 레지스터로 이동 한 다음 shufps
이 스칼라 값을 전체 벡터에 복사하는 데 사용 하는 작업 후에 추가 명령이 있지만 일정이 변경되지 않은 것처럼 보입니다 . 가중치 벡터는 mulps
부하에서 부동 소수점 도메인으로의 전환 지연을 고려하여 당분간 사용할 준비가 된 것 같으 므로 추가 지연이 발생하지 않아야합니다.
movaps
(정렬, 포장 이동), addps
및 mulps
이 중 여분의 대기 시간이 발생해서는 안 (어셈블리 코드로 확인)이 커널에 사용되는 지침은, 자신의 스칼라 버전과 동일한 지연 시간 및 처리량을 가지고있다.
이 커널이 얻을 수있는 최대 성능이주기 당 6.4FP 작업이고주기 당 5.6FP 작업으로 실행되고 있다고 가정 할 때 8주기 당 추가주기가 어디에 사용되는지 아는 사람이 있습니까?
참고로 실제 어셈블리는 다음과 같습니다.
…
Block x:
movapsx (%rax,%rcx,4), %xmm0
movapsx 0x10(%rax,%rcx,4), %xmm1
movapsx 0x20(%rax,%rcx,4), %xmm2
movapsx 0x30(%rax,%rcx,4), %xmm3
movssl (%rdx,%rcx,4), %xmm4
inc %rcx
shufps $0x0, %xmm4, %xmm4 {fill weight vector}
cmp $0x32, %rcx
mulps %xmm4, %xmm0
mulps %xmm4, %xmm1
mulps %xmm4, %xmm2
mulps %xmm3, %xmm4
addps %xmm0, %xmm5
addps %xmm1, %xmm6
addps %xmm2, %xmm7
addps %xmm4, %xmm8
jl 0x401ad6 <Block x>
…
shufps
명령이 1.6 반복마다 1 사이클을 추가합니까?"입니다. 즉 ... 힘든 하나