처음에는 파트 토론 부분 해결 형 질문 일 수 있습니다. 그 누구도 기분을 상하게 할 의도가 없습니다.부동 소수점 명령어로 부과되는로드를 이해하고 싶습니다.
64 비트 어셈블리에 MT Prime 기반 난수 생성기를 64 비트 생성하는 알고리즘을 작성했습니다.
이 발생 기능이 크기 2048x2048x2048의 배열을 채우고 1..small_value 사이의 임의의 어떤을 생성하기 위해 80 억 번 호출 할 필요가있다 (보통, 32)
는 지금은 두 다음 단계의 가능성이 있었다 (a) 숫자를 생성하고 제한값 [1..32]과 비교하여 그 범위를 벗어나는 값을 버린다. 이 로직의 실행 시간은 clock() 함수를 호출하여 측정 한 181,817ms입니다.
(b) RAX에서 출력되는 64 비트 난수를 가져 와서 FPU를 사용하여 [0..1] 사이의 값으로 스케일 한 다음 원하는 범위 [1..32]로 스케일합니다. 코드 시퀀스
mov word ptr initialize_random_number_scaling,dx
fnclex ; clears status flag
call generate_fp_random_number ; returns a random number in ST(0) between [0..1]
fimul word ptr initialize_random_number_scaling ; Mults ST(0) & stores back in ST(0)
mov word ptr initialize_random_number_base,ax ; Saves base to a memory
fiadd word ptr initialize_random_number_base ; adds the base to the scaled fp number
frndint ; rounds off the ST(0)
fist word ptr initialize_random_number_result ; and stores this number to result.
ffree st(0) ; releases ST(0)
fincstp ; Logically pops the FPU
mov ax, word ptr initialize_random_number_result ; and saves it to AX
그리고 generate_fp_random_number의 지침은 다음과 같습니다 :이 다음과 같습니다에 대한
shl rax,1 ; RAX gets the original 64 bit random number using MT prime algorithm
shr ax,1 ; Clear top bit
mov qword ptr random_number_generator_act_number,rax ; Save the number in memory as we cannot move to ST(0) a number from register
fild qword ptr random_number_generator_max_number ; Load 0x7FFFFFFFFFFFFFFFH
fild qword ptr random_number_generator_act_number ; Load our number
fdiv st(0),st(1) ; We return the value through ST(0) itself, divide our random number with max possible number
fabs
ffree st(1) ; release the st(1)
fld1 ; push to top of stack a 1.0
fcomip st(0), st(1) ; compares our number in ST(1) with ST(0) and sets CF.
jc generate_fp_random_get_next_no ; if ST(0) (=1.0) < ST(1) (our no), we need a new no
fldz ; push to top of stack a 0.0
fcomip st(0),st(1) ; if ST(0) (=0.0) >ST(1) (our no) clears CF
jnc generate_fp_random_get_next_no ; so if the number is above zero the CF will be set
fclex
문제는 바로 이러한 지침을 추가하여,이다, 실행 시간은 무려 5,633,963 MS로 이동합니다! 나는 대안으로 xmm 레지스터를 사용하여 위 코드를 작성했으며 그 차이는 절대적으로 적다. (5,633,703 ms).
누구나 친절하게도이 추가 지침이 전체 실행 시간에 어느 정도 부하를 걸 었는지에 관해 안내해 줄 수 있습니까? FPU가 정말로 느린가? 아니면 트릭을 놓치고 있습니까? 항상 그렇듯이 모든 아이디어는 환영하며 시간과 노력에 감사드립니다.
봉투 : "MOV 단어의 PTR initialize_random_number_base, 도끼, 메모리에 기반을 저장합니다"윈도우 7 64 비트 인텔에 2700K CPU는 16기가바이트 RAM은 VS 2012 익스프레스 환경
이것은 자체 수정 코드가 아니며 어셈블리에도 완전히 쓰여 있습니다. 변수 initialize_random_number_base는 데이터 세그먼트에서 정의 단어로 선언됩니다.이 값은 2K보다 훨씬 큽니다. 그러나주의는 정말로 유용합니다. 고마워. 따라서 데이터 세그먼트에 불필요한 공간을 추가 했으므로 코드 세그먼트와 2K가 넘습니다. – quasar66