제공된 코드에서 __mm_add_epi32_inplace_purego 함수를 어셈블리를 사용하여 최적화할 수 있습니다. 성능을 향상시킵니다. 특히 내부 루프는 더 빠른 실행을 위해 최적화될 수 있습니다.
위치 인구 계산을 위해 제공된 알고리즘을 "위치 인구 카운트"라고 합니다. 이 알고리즘은 기계 학습에 사용되며 일련의 바이트에서 설정된 비트 수를 계산하는 것과 관련됩니다. 주어진 코드에서 _mm_add_epi32_inplace_purego는 두 가지 수준의 루프에서 호출되며 목표는 내부 루프를 최적화하는 것입니다.
제공된 코드는 주로 다음과 같은 8비트 정수 배열에서 작동합니다. 중요합니다. 내부 루프는 바이트 슬라이스를 반복하고 각 바이트에 대해 비트 패턴 배열(_expand_byte)의 해당 비트 위치를 카운트 배열에 추가합니다. _expand_byte 배열에는 각 바이트를 개별 비트로 확장하는 비트 패턴이 포함되어 있습니다.
내부 루프를 최적화하려면 어셈블리를 사용하여 더 나은 성능과 성능을 위해 카운터를 범용 레지스터에 유지해야 합니다. 스트리밍 동작을 개선하기 위해 메모리를 미리 미리 가져옵니다. 간단한 시프트 및 추가 조합(SHRL/ADCL)을 사용하여 스칼라 인구 계산을 구현할 수도 있습니다.
최적화된 어셈블리 코드의 예가 아래에 나와 있습니다. 이 코드는 특정 프로세서 아키텍처용으로 작성되었으며 다른 시스템에서 실행하려면 수정해야 할 수도 있습니다.
<code class="assembly">#include "textflag.h" // func PospopcntReg(counts *[8]int32, buf []byte) TEXT ·PospopcntReg(SB),NOSPLIT,-32 MOVQ counts+0(FP), DI MOVQ buf_base+8(FP), SI // SI = &buf[0] MOVQ buf_len+16(FP), CX // CX = len(buf) // load counts into register R8--R15 MOVL 4*0(DI), R8 MOVL 4*1(DI), R9 MOVL 4*2(DI), R10 MOVL 4*3(DI), R11 MOVL 4*4(DI), R12 MOVL 4*5(DI), R13 MOVL 4*6(DI), R14 MOVL 4*7(DI), R15 SUBQ , CX // pre-subtract 32 bit from CX JL scalar vector: VMOVDQU (SI), Y0 // load 32 bytes from buf PREFETCHT0 384(SI) // prefetch some data ADDQ , SI // advance SI past them VPMOVMSKB Y0, AX // move MSB of Y0 bytes to AX POPCNTL AX, AX // count population of AX ADDL AX, R15 // add to counter VPADDD Y0, Y0, Y0 // shift Y0 left by one place VPMOVMSKB Y0, AX // move MSB of Y0 bytes to AX POPCNTL AX, AX // count population of AX ADDL AX, R14 // add to counter VPADDD Y0, Y0, Y0 // shift Y0 left by one place VPMOVMSKB Y0, AX // move MSB of Y0 bytes to AX POPCNTL AX, AX // count population of AX ADDL AX, R13 // add to counter VPADDD Y0, Y0, Y0 // shift Y0 left by one place VPMOVMSKB Y0, AX // move MSB of Y0 bytes to AX POPCNTL AX, AX // count population of AX ADDL AX, R12 // add to counter VPADDD Y0, Y0, Y0 // shift Y0 left by one place VPMOVMSKB Y0, AX // move MSB of Y0 bytes to AX POPCNTL AX, AX // count population of AX ADDL AX, R11 // add to counter VPADDD Y0, Y0, Y0 // shift Y0 left by one place VPMOVMSKB Y0, AX // move MSB of Y0 bytes to AX POPCNTL AX, AX // count population of AX ADDL AX, R10 // add to counter VPADDD Y0, Y0, Y0 // shift Y0 left by one place VPMOVMSKB Y0, AX // move MSB of Y0 bytes to AX POPCNTL AX, AX // count population of AX ADDL AX, R9 // add to counter VPADDD Y0, Y0, Y0 // shift Y0 left by one place VPMOVMSKB Y0, AX // move MSB of Y0 bytes to AX POPCNTL AX, AX // count population of AX ADDL AX, R8 // add to counter SUBQ , CX JGE vector // repeat as long as bytes are left scalar: ADDQ , CX // undo last subtraction JE done // if CX=0, there's nothing left loop: MOVBLZX (SI), AX // load a byte from buf INCQ SI // advance past it SHRL , AX // CF=LSB, shift byte to the right ADCL , R8 // add CF to R8 SHRL , AX ADCL , R9 // add CF to R9 SHRL , AX ADCL , R10 // add CF to R10 SHRL , AX ADCL , R11 // add CF to R11 SHRL , AX ADCL , R12 // add CF to R12 SHRL , AX ADCL , R13 // add CF to R13 SHRL , AX ADCL , R14 // add CF to R14 SHRL , AX ADCL , R15 // add CF to R15 DECQ CX // mark this byte as done JNE loop // and proceed if any bytes are left // write R8--R15 back to counts done: MOVL R8, 4*0(DI) MOVL R9, 4*1(DI) MOVL R10, 4*2(DI) MOVL R11, 4*3(DI) MOVL R12, 4*4(DI) MOVL R13, 4*5(DI) MOVL R14, 4*6(DI) MOVL R15, 4*7(DI) VZEROUPPER // restore SSE-compatibility RET</code>
요약하면 최적화에는 카운터에 범용 레지스터를 사용하는 작업이 포함됩니다. 메모리를 미리 가져오고 SHRL/ADCL을 사용하여 스칼라 인구 계산을 구현합니다. 이 접근 방식은 위치 인구 수 알고리즘의 성능을 크게 향상시킬 수 있습니다.
위 내용은 어셈블리를 사용하여, 특히 내부 루프에 초점을 맞추고 프리패치 및 스칼라 모집단 계산과 같은 기술을 활용하여 8비트 위치 팝카운트 알고리즘을 어떻게 최적화할 수 있습니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!