어셈블리를 사용하여, 특히 내부 루프에 초점을 맞추고 프리패치 및 스칼라 모집단 계산과 같은 기술을 활용하여 8비트 위치 팝카운트 알고리즘을 어떻게 최적화할 수 있습니까?

Patricia Arquette
풀어 주다: 2024-10-27 09:02:30
원래의
1000명이 탐색했습니다.

How can you optimize an 8-bit positional popcount algorithm using assembly, specifically by focusing on the inner loop and utilizing techniques like prefetching and scalar population counting?

어셈블리를 사용하여 이 8비트 위치 팝카운트를 최적화하는 방법은 무엇입니까?

제공된 코드에서 __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 중국어 웹사이트의 기타 관련 기사를 참조하세요!

원천:php.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
저자별 최신 기사
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿
회사 소개 부인 성명 Sitemap
PHP 중국어 웹사이트:공공복지 온라인 PHP 교육,PHP 학습자의 빠른 성장을 도와주세요!