簡體   English   中英

AVX-512 - 如何使用匯編指令從 memory 收集數據?

[英]AVX-512 - How to gather data from memory using assembly instruction?

我正在嘗試使用匯編指令從 memory 收集 64 位整數。 您可以在下面看到我如何從C調用assembly代碼。 請注意,匯編代碼使用NASM語法。

nasm_gather.asm文件

bits 64

        section .text
global nasm_gather:function

extern base_addr
extern vindex

nasm_gather:
        ; prolog
        push            rbp
        push            rbx
        push            r12
        push            r13

        mov             r12         ,[rel base_addr]                ; r12 point to base_addr
        mov             r13         ,[rel vindex]                   ; r13 points to vindex
        vmovdqu32       zmm1        ,[r13]                          ; zmm1 = [2, 5, 1, 3, 0, 4, 7, 6]
        vpxorq          zmm2        ,zmm2               ,zmm2       ; zmm2 = [0, 0, 0, 0, 0, 0, 0, 0]
        vpgatherqq      zmm2        ,[r12 + zmm1*8]                 ; ----> Illegal instruction at address = ...
        ...
        ; epilog
        pop             r13
        pop             r12
        pop             rbx
        pop             rbp
        ret

main.cpp文件

#include <iostream>
#include <immintrin.h>

using namespace std;

extern "C" int nasm_gather();

const int N=32;
int64_t* base_addr /*__attribute__ ((aligned (64)))*/  = (int64_t *) malloc(sizeof(int64_t) * N);
int64_t* vindex =  (int64_t *) malloc(sizeof(int64_t) * 8);


int main() {
    /* initialize indices */
    vindex[0]=2; vindex[1]=5; vindex[2]=1; vindex[3]=3;
    vindex[4]=0; vindex[5]=4; vindex[6]=7; vindex[7]=6;
    // ...
    int64_t result = nasm_gather();
    ...

    return 0;
}

vpgatherqq zmm, vm64z匯編指令對應於 C 中的_mm512_i64gather_epi64內在 function)

正如程序到達這一點:

vpgatherqq      zmm2        ,[r12 + zmm1*8]

我收到非法指令錯誤:

地址 = 4011f0 處的非法指令:62 d2 fd 48 91 14 cc 62 f1 7e 48 6f c2 e8 10
如果您認為您的應用程序應該嘗試執行此非法指令(以及可能存在的其他指令),請使用此旋鈕:-emit-illegal-insts 0 並且將避免此錯誤消息。

有什么問題?

聚會需要一個面具(這樣他們就可以在被打斷或某個元素出現故障時記錄進度)。 NASM 通常不會讓你在沒有警告的情況下匯編非法指令。 這是一個 NASM 錯誤,它不能幫助您發現此錯誤。

此外,您使用全局變量而不是 function 參數的整個方法對可維護性和性能都不利。 如果您已經願意告訴 GCC 它可以發出 AVX-512 指令 ( -march=skylake-avx512 ) 並在源代碼中#include <immintrin.h> ,請像普通人一樣使用內在函數 例如_mm512_mask_i64gather_epi64 完全調用任何 function 而不是內聯收集指令將花費收集成本的很大一部分,而且如果它是一個笨拙低效的 function 編寫方式,則更多。 如果您的索引尚未在 SIMD 向量中,則收集是非常有問題的,並且使用存儲在全局變量中的指針作為索引肯定無濟於事,而不是為收集 function 傳遞指針 arg 來加載向量來自某處的索引。


以下代碼在 SDE 8.33.0、NASM 2.15.05 中運行良好 您聲稱添加{k1}並不能解決您的問題。 要么你的 SDE 版本壞了,要么你做錯了什么。 或者您忘記從更新的源代碼重建可執行文件。

default rel
global _start
_start:
    lea     rax, [rel buf]      ; dummy base = static array.  In a function, use RDI (first int/pointer arg)
    vpxor   xmm1, xmm1,xmm1     ; ZMM1 = dummy index = all zeros, efficiently done with a VEX-coded AVX instruction

    kxnorb      k1, k0,k0           ; mask = -1
    vpxor       xmm0, xmm0,xmm0     ; optional: dependency-breaking before merge-masking.  GCC will do this for the intrinsic.
    vpgatherqq  zmm0{k1}, [rax + zmm1*8]
        
    mov eax, 231
    syscall             ; exit_group(RDI)

section .bss
buf: resd 1024

如果我刪除{k1} ,我可以重現該 SDE 錯誤消息,使其像你原來的問題一樣被揭露。 如果您嘗試使用{k1}{z} ,則 NASM 2.15.05 錯誤 - Gathers 僅支持合並屏蔽(同樣,它可以在被 #PF 中斷或可能中斷的部分執行后恢復)。 但是使用正確的源代碼,它可以在 static 可執行文件中正常構建和運行。 主機 CPU 是 i7-6700k Skylake 客戶端(它不支持 AVX-512,因此由 SDE 決定)。

$ nasm -felf64 avx512-gather.asm
$ ld -o avx512-gather avx512-gather.o
$ /opt/sde-external-8.33.0-2019-02-07-lin/sde64 -- ./avx512-gather
$ echo $?
0

(當然, sde64 -icl也可以。)

Linking the same machine code into a function callable from C++ would run the same way, but again, that would be pointless when you can use intrinsics (and disassemble with objdump -drwC -Mintel a.out to see how GCC used the instruction.)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM