【问题标题】:Alignment issue in assembly(NASM) [duplicate]装配中的对齐问题(NASM)[重复]
【发布时间】:2021-12-04 03:58:24
【问题描述】:

我正在尝试手动对从数组中读取元素所花费的时间进行基准测试,因此我创建了一个从传递的数组中读取的汇编代码。
示例汇编代码:

; void array_read(long n, double *A);
; n must be divisible by 64

section .text

%ifidn __OUTPUT_FORMAT__, macho64
%define array_read _array_read
%endif

global array_read

array_read:
        ;   rdi = n
        ;   rsi = A
        ;   rax = i
        push rbx
        mov rax, 0
        align 16
.main_loop:
        vmovaps ymm0,  [rsi+8*(rax+ 0)]
        vmovaps ymm1,  [rsi+8*(rax+ 4)]
        vmovaps ymm2,  [rsi+8*(rax+ 8)]
        vmovaps ymm3,  [rsi+8*(rax+12)]
        add rax, 64
        cmp rax, rdi
        jl .main_loop
.epilog:
        ; Restore caller registers
        pop rbx
        ret

我很幸运在 MacOS(Intel) 中它可以正确对齐并提供所需的输出,但在 Linux 中它提供了

Program received signal SIGSEGV: Segmentation fault - invalid memory reference.

Backtrace for this error:
#0  0x7fe37cdee20f in ???
#1  0x557940d91600 in ???
Segmentation fault (core dumped)

为什么会出现分段错误?

【问题讨论】:

  • 您是在问如何首先在调用者中分配对齐的缓冲区吗?如果是这样,它甚至是用asm写的吗?如果没有,How to solve the 32-byte-alignment issue for AVX load/store operations?。或者您是否在询问处理数组的第一个可能未对齐的向量然后进行对齐加载的实现策略? (如果调用者传递一个未对齐的缓冲区,而不是仅仅使用vmovups 让硬件处理缓存行拆分的次要性能成本)
  • 我认为在调用组装方法时需要传递对齐的数据。这比试图在这里对齐要好。
  • 另外,这里 RBX 的 push/pop 有什么意义?您的循环不需要任何保留调用的寄存器。它也不需要索引;它可以只增加指针。
  • array A 存储了随机值,方法是将 A 传递给 Fortran 中的 random_number 函数。
  • 为什么会出现段错误?因为您将未对齐的指针传递给使用 vmovaps 的函数,该函数需要 32 字节对齐。阅读vmovaps (felixcloutier.com/x86/movaps) 与vmovups 的手册。如果您想了解 Fortran 内存对齐规则,以及如何要求更多对齐,请改为询问。在 x86-64 System V ABI 中,alignof(max_align_t) 是 16,因此 malloc 之类的东西只能保证返回具有那么多对齐的内存。 (也适用于全局数组)。

标签: assembly nasm memory-alignment avx


【解决方案1】:

在 C++ 中,尝试像这样调用你的函数:

alignas(32) double arr[16];
read_array(sizeof(arr), arr);

【讨论】:

    猜你喜欢
    • 2011-07-09
    • 2011-01-15
    • 2021-05-14
    • 2019-06-25
    • 2015-08-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多