混合组装和 Fortran 以及并行化 (OpenMP)

Posted

技术标签:

【中文标题】混合组装和 Fortran 以及并行化 (OpenMP)【英文标题】:Mixing Assembly & Fortran plus parallelization (OpenMP) 【发布时间】:2014-11-21 08:18:16 【问题描述】:

我现在正在尝试以下方法:

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 线程的本地?如果它们是共享的,那么竞争条件和类似的东西如何?

我希望我已经足够清楚了。

【问题讨论】:

实际上,CPU 有更多的寄存器,即使对于串行程序,名称也与内核中的一个不同的物理寄存器不一致。 【参考方案1】:

每个线程都有自己的一组寄存器。这在线程在不同内核上执行的情况下很明显,因为每个内核都包含一整套寄存器。当多个线程分时共享同一个物理内核时,用户可见寄存器的状态会在执行切换到不同线程时保存,然后在执行切换回原始线程时恢复(上下文保存/恢复),从而产生每个线程只在寄存器上操作的错觉。

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

mov [rdi], rax
xor rax, rax

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

【讨论】:

我最近了解到的一件有趣的事情是,在 Sandy Bridge xor rax 上,rax 甚至不使用微操作。寄存器文件有一个零寄存器,rax 寄存器被重命名为。唯一的成本是解码指令。但这很少是问题。 我最初的想法是mov [rdi], rax; mov rax, [rsi],但后来我决定用不同的东西替换第二个mov。我也不知道零寄存器。 如果你有兴趣我在这里了解了***.com/questions/26807285/…

以上是关于混合组装和 Fortran 以及并行化 (OpenMP)的主要内容,如果未能解决你的问题,请参考以下文章

开放式加速器 | Fortran 90:并行化嵌套 DO 循环的最佳方法是啥?

如何在由 MPI 并行化的 fortran 中调用子例程?

Fortran 95 构造(例如 WHERE、FORALL 和 SPREAD)通常会导致更快的并行代码吗?

OpenACC + MPI Fortran 程序入门

[转载:]C#与Fortran混合编程之本地调用Fortran动态链接库

无法并行化OpenACC循环