다시 한번 기본 어셈블리 언어를 다시 가르치기 위해 다시 뛰어 들고 있으므로 모든 것을 완전히 잊지는 않습니다.SIMD 연산 결과가 배열로 돌아가는 방법 : 캐시 비호 환적입니까?
나는이 연습 코드를 만들었습니다. 그리고 그 안에, 벡터 연산의 결과를 배열에 거꾸로 넣어야한다는 것이 밝혀졌습니다. 그렇지 않으면 틀린 대답을했습니다. 덧붙여 말하자면, 이것은 GCC가 SIMD 연산 결과를 메모리 위치로 되돌려 보내는 것과 마찬가지로 어셈블리 코드를 출력하는 방법이기도하므로 "올바른"방법이라고 생각합니다.
그러나 오랜 시간 동안 게임 개발자로서 의식 해 왔던 뭔가, 캐시의 친숙 함에서 뭔가가 생겼습니다. 내 이해는 인접한 메모리 블록에서 앞으로 나아가는 것이 항상 이상적이며, 그렇지 않으면 캐시 미스가 발생할 위험이 있습니다.
내 질문은 : 아래의 예제가 두 개의 4 요소 벡터를 계산하고 종료하기 전에 네 개의 숫자를 내뱉는 것 이상이라도 기술적으로 무엇인가 배열에 다시 입력해야하는지 궁금합니다. 역순으로 - 실제 세계에서 캐시 미스에 영향을 미칩니다. 초당 수십만 건의 SIMD 벡터 계산 (더 구체적으로 메모리로 반환)을 수행하는 일반적인 프로덕션 수준의 프로그램에서 그렇습니다. 여기
는 stackexchange하는 나의이 호기심을 가지고 나를하라는 메시지가 원래 포함 주석이있는 전체 코드 (리눅스 64 비트 NASM)입니다 :extern printf
extern fflush
global _start
section .data
outputText: db '[%f, %f, %f, %f]',10,0
align 16
vec1: dd 1.0, 2.0, 3.0, 4.0
vec2: dd 10.0,10.0,10.0,50.0
section .bss
result: resd 4 ; four 32-bit single-precision floats
section .text
_start:
sub rsp,16
movaps xmm0,[vec1]
movaps xmm1,[vec2]
mulps xmm0,xmm1 ; xmm0 = (vec1 * vec2)
movaps [result],xmm0 ; copy 4 floats back to result[]
; printf only accepts 64-bit floats for some dumb reason,
; so convert these 32-bit floats packed within the 128-bit xmm0
; register into four 64-bit floats, each in a separate xmm* reg
movss xmm0,[result+12] ; result[3]
unpcklps xmm0,xmm0 ; 32-->64 bit
cvtps2pd xmm3,xmm0 ; put double in 4th XMM
movss xmm0,[result+8] ; result[2]
unpcklps xmm0,xmm0 ; 32-->64 bit
cvtps2pd xmm2,xmm0 ; put double in 3rd XMM
movss xmm0,[result+4] ; result[1]
unpcklps xmm0,xmm0 ; 32-->64 bit
cvtps2pd xmm1,xmm0 ; put double in 2nd XMM
movss xmm0,[result] ; result[0]
unpcklps xmm0,xmm0 ; 32-->64 bit
cvtps2pd xmm0,xmm0 ; put double in 1st XMM
; FOOD FOR THOUGHT!
; *****************
; That was done backwards, going from highest element
; of what is technically an array down to the lowest.
;
; This is because when it was done from lowest to
; highest, this garbled bird poop was the answer:
; [13510801139695616.000000, 20.000000, 30.000000, 200.000000]
;
; HOWEVER, if the correct way is this way, in which
; it traipses through an array backwards...
; is that not cache-unfriendly? Or is it too tiny and
; miniscule to have any impact with cache misses?
mov rdi, outputText ; tells printf where is format string
mov rax,4 ; tells printf to print 4 XMM regs
call printf
mov rdi,0
call fflush ; ensure we see printf output b4 exit
add rsp,16
_exit:
mov eax,1 ; syscall id for sys_exit
mov ebx,0 ; exit with ret of 0 (no error)
int 80h