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


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

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

    其中,宏 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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    进行宏替换后可知,当调用 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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    上面有意敲了回车,是为了看的更清楚一些。上面第 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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68

    进行宏替换后可知,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
    
    • 1
    • 2
    • 3
    • 4
    • 5

    同时,将其值保存在 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

  • 相关阅读:
    IB和A-level物理怎么选?
    java高校会议室预约系统计算机毕业设计MyBatis+系统+LW文档+源码+调试部署
    Chrome Extensions v3 迁移清单
    P2678 [NOIP2015 提高组] 跳石头——二分答案
    PyQt5 信号(Signal)与槽(Slot)
    wpf-窗口设计-常用小技巧
    【ARMv8 SIMD和浮点指令编程】NEON 乘法指令——asimdrdm
    Codeforces Round #831 (Div. 1 + Div. 2)——A、B、C、D、E
    RV-GAN:使用新的多尺度生成对抗网络分割眼底照片中的视网膜血管结构
    数据结构--队列与循环队列的实现
  • 原文地址:https://blog.csdn.net/choumin/article/details/126706310