isa-l 中硬件优化函数的调用路径

下面以 isa-lec_encode_data()函数为例,弄清楚该函数对应的硬件优化版本的调用路径。
这里面涉及两个重要的步骤:接口定义函数选择。之所以要进行函数选择,是因为不同的 CPU feature对应了不同的实现,具体来说就是,根据 CPU是否支持 SSE4.2AVX2AVX512feature,选择不同的硬件指令实现。

  1. 接口定义
    isa-l/erasure_code/ec_multibinary.asm文件中,存在如下语句:
mbin_interface ec_encode_data

其中,宏 mbin_interface定义在 isa-l/include/multibinary.asm中,内容如下:

;;;;
; multibinary macro:
;   creates the visable entry point that uses HW optimized call pointer
;   creates the init of the HW optimized call pointer
;;;;
%macro mbin_interface 1
    ;;;;
    ; *_dispatched is defaulted to *_mbinit and replaced on first call.
    ; Therefore, *_dispatch_init is only executed on first call.
    ;;;;
    section .data
    %1_dispatched:
        mbin_def_ptr    %1_mbinit
 
    section .text
    mk_global %1, function
    %1_mbinit:
        endbranch
        ;;; only called the first time to setup hardware match
        call    %1_dispatch_init
        ;;; falls thru to execute the hw optimized code
    %1: 
        endbranch
        jmp mbin_ptr_sz [%1_dispatched]
%endmacro

进行宏替换后可知,当调用 ec_encode_data后,函数跳转至 ec_encode_data_dispatched处执行,在第一次调用 ec_encode_data时,ec_encode_data_dispatched处的函数为 ec_encode_data_mbinit,该函数将根据硬件特征设置最合适的硬件指令优化函数,具体工作由 ec_encode_data_dispatch_init完成。

  1. 函数选择
    同样的,还是在 isa-l/erasure_code/ec_multibinary.asm文件中,存在如下语句:
mbin_dispatch_init6 ec_encode_data, \
ec_encode_data_base, \
ec_encode_data_sse, \
ec_encode_data_avx, \
ec_encode_data_avx2, \
ec_encode_data_avx512

上面有意敲了回车,是为了看的更清楚一些。上面第 26行的 5个函数均是 ec_encode_data的备选函数。值得注意的是,第一个备选函数 ec_encode_data_base是不带硬件指令优化的C语言版本。其中,宏 mbin_dispatch_init6定义在 isa-l/include/multibinary.asm文件中,内容如下:

;;;;;       
; mbin_dispatch_init6 parameters
; 1-> function name
; 2-> base function
; 3-> SSE4_2 or 00/01 optimized function
; 4-> AVX/02 opt func
; 5-> AVX2/04 opt func
; 6-> AVX512/06 opt func
;;;;;       
%macro mbin_dispatch_init6 6
    section .text
    %1_dispatch_init:
        push    mbin_rsi
        push    mbin_rax
        push    mbin_rbx
        push    mbin_rcx
        push    mbin_rdx
        push    mbin_rdi
        lea mbin_rsi, [%2 WRT_OPT] ; Default - use base function
            
        mov eax, 1
        cpuid
        mov ebx, ecx ; save cpuid1.ecx
        test    ecx, FLAG_CPUID1_ECX_SSE4_2
        je  _%1_init_done     ; Use base function if no SSE4_2
        lea mbin_rsi, [%3 WRT_OPT] ; SSE possible so use 00/01 opt
            
        ;; Test for XMM_YMM support/AVX
        test    ecx, FLAG_CPUID1_ECX_OSXSAVE
        je  _%1_init_done
        xor ecx, ecx 
        xgetbv  ; xcr -> edx:eax
        mov edi, eax      ; save xgetvb.eax
            
        and eax, FLAG_XGETBV_EAX_XMM_YMM
        cmp eax, FLAG_XGETBV_EAX_XMM_YMM
        jne _%1_init_done
        test    ebx, FLAG_CPUID1_ECX_AVX
        je  _%1_init_done
        lea mbin_rsi, [%4 WRT_OPT] ; AVX/02 opt
            
        ;; Test for AVX2
        xor ecx, ecx 
        mov eax, 7
        cpuid
        test    ebx, FLAG_CPUID7_EBX_AVX2
        je  _%1_init_done       ; No AVX2 possible
        lea mbin_rsi, [%5 WRT_OPT]  ; AVX2/04 opt func

        ;; Test for AVX512
        and edi, FLAG_XGETBV_EAX_ZMM_OPM
        cmp edi, FLAG_XGETBV_EAX_ZMM_OPM
        jne _%1_init_done     ; No AVX512 possible
        and ebx, FLAGS_CPUID7_EBX_AVX512_G1
        cmp ebx, FLAGS_CPUID7_EBX_AVX512_G1
        lea mbin_rbx, [%6 WRT_OPT] ; AVX512/06 opt
        cmove   mbin_rsi, mbin_rbx
         
    _%1_init_done:
        pop mbin_rdi
        pop mbin_rdx
        pop mbin_rcx
        pop mbin_rbx
        pop mbin_rax
        mov [%1_dispatched], mbin_rsi
        pop mbin_rsi
        ret
%endmacro

进行宏替换后可知,ec_encode_data_dispatch_init将根据 CPU feature从以下几个函数中选出最合适的一个:

ec_encode_data_base,
ec_encode_data_sse,
ec_encode_data_avx,
ec_encode_data_avx2,
ec_encode_data_avx512

同时,将其值保存在 mbin_rsi中。接着,在 ec_encode_data_init_done里面,通过
mov [%1_dispatched], mbin_rsi语句更新了 ec_encode_data_dispatched的值。

ec_encode_data_mbinit函数执行完后,又调用了 ec_code_data函数,此时还是跳转至 ec_encode_data_dispatched处执行,但由于在第一次调用 ec_code_data后,ec_encode_data_dispatched的值被更新了,因此在第二次以及后续调用 ec_encode_data_dispatched时,执行的都是硬件优化版本的 ec_code_data

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值