混合装配& Fortran加并行化(OpenMP)

时间:2014-11-21 08:18:16

标签: assembly parallel-processing fortran openmp race-condition

我现在正在尝试下面的事情:

global  func_
func_:
    push rbp
    mov rbp, rsp

    mov rax,[rdi]
    mov rbx,[rsi]

    cmp rbx,1
    je  done
    dec rbx

    mov rsi,1
loop1:
    shl rsi, 1
    dec     rbx
    jnz     loop1

    or rax,rsi
    mov [rdi],rax

    mov rcx,15
    mov rax,11
    movq xmm1,rcx
    movq xmm0, rax
    xorpd xmm0, xmm1

    movq rax, xmm0
    mov [rdi],rax


    mov rsp, rbp
    pop rbp
    ret

done:

    or rax,1
    mov [rdi],rax
    mov rsp, rbp
    pop rbp
    ret

到目前为止,代码实际上没有意义,我将需要使用XMM [](128位按位操作),这个汇编代码应该编译成一个对象并链接到Fortran代码,我将:

! Compile:
!gfortran -c testassembly.F90; 
!nasm -f elf64 assembly_func.asm; 
!gfortran -o run testassembly.o assembly_func.o; 
!./run

a = 10
b = 4
call func(a,b)

到目前为止,一切都很清楚,现在如果我为此会发生什么。 OpenMP平行化我的代码,即:

!$omp do schedule(dynamic,1)
a = 10
b = 4
call func(a,b)
!$omp end do

换句话说,汇编中的寄存器是否存在物理存在?或者它们将以某种方式在OpenMP线程本地?如果他们被分享,竞争条件和类似的东西怎么样?

我希望我足够清楚。

1 个答案:

答案 0 :(得分:3)

每个线程都有自己的一组寄存器。当线程在不同的内核上执行时,这是显而易见的,因为每个内核都包含一整套寄存器。当多个线程分时共享同一个物理内核时,当执行切换到另一个线程时会保存用户可见寄存器的状态,然后在执行切换回原始线程时进行恢复(上下文保存/恢复),从而给出了每个线程专门在寄存器上运行的错觉。

至于那些寄存器的物理存在,现代的x86 CPU在它们的核心中没有称为RAX,RBX等的固定单元。它们借用旧的RISC概念,而它们所拥有的是大量的寄存器寄存器文件(实际上,现代x86 CPU基本上是RISC内核,每个CISC指令被分成一组简单的操作,称为微操作的核心)。该文件中的每个寄存器都可以通过称为寄存器重命名的过程充当RAX。例如,这允许独立指令并行执行,即使它们使用相同的寄存器,例如

mov [rdi], rax
xor rax, rax

在这种情况下,第二条指令对第一条指令没有数据依赖性,因为rax的内容只是被覆盖。但是如果有一个RAX寄存器,则CPU必须首先完成第一条指令的写入到存储器级,然后第二条指令才能使用RAX。通过寄存器重命名,第二条指令只是从文件写入另一个寄存器,从那时起用作RAX。