混合组装和 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 循环的最佳方法是啥?
Fortran 95 构造(例如 WHERE、FORALL 和 SPREAD)通常会导致更快的并行代码吗?