相关疑难解决方法(0)

我什么时候应该使用_mm_sfence _mm_lfence和_mm_mfence

我阅读了"英特尔架构的英特尔优化指南指南".

但是,我仍然不知道何时应该使用

_mm_sfence()
_mm_lfence()
_mm_mfence()
Run Code Online (Sandbox Code Playgroud)

任何人都可以解释在编写多线程代码时何时应该使用它们?

c++ x86 multithreading intrinsics memory-barriers

14
推荐指数
3
解决办法
6488
查看次数

lock xchg与mfence具有相同的行为吗?

我想知道的是lock xchg,mfence从一个线程访问内存位置的角度来看是否会有类似的行为,这个内存位置正在被其他线程进行变异(让我们随便说).它能保证我获得最新的价值吗?之后的内存读/写指令?

我混淆的原因是:

8.2.2"读取或写入不能通过I/O指令,锁定指令或序列化指令重新排序."

-Intel 64 Developers Manual Vol.3

这是否适用于线程?

mfence 状态:

对MFENCE指令之前发出的所有内存加载和存储到内存指令执行序列化操作.此序列化操作保证在MFENCE指令之前的任何加载或存储指令全局可见之前,在程序顺序之前的每条加载和存储指令都是全局可见的.MFENCE指令针对所有加载和存储指令,其他MFENCE指令,任何SFENCE和LFENCE指令以及任何序列化指令(例如CPUID指令)进行排序.

-Intel 64 Developers Manual Vol 3A

听起来更有力.因为它听起来mfence几乎正在刷写写缓冲区,或者至少延伸到写缓冲区和其他内核以确保我未来的加载/存储是最新的.

当基准标记时,两个指令都需要约100个循环才能完成.所以我无论如何都看不出那么大的差异.

主要是我只是困惑.我的指令基于lock互斥体使用,但后来这些包含没有内存栅栏.然后,我看到锁免费使用内存栅栏编程,但没有锁.我知道AMD64有一个非常强大的内存模型,但过时的值可以在缓存中持续存在.如果lock行为与行为不同,mfence那么互斥量如何帮助您查看最新值?

x86 assembly multithreading cpu-architecture memory-barriers

10
推荐指数
1
解决办法
1145
查看次数

汇编中的递归Fibonacci

我正在尝试在Assembly中实现递归的Fibonacci程序.但是,我的程序崩溃,有一个未处理的异常,我似乎无法找出问题.我不怀疑它涉及我对堆栈的不当使用,但我似乎无法指出哪里......

.386
.model Flat
public Fibonacci
include iosmacros.inc ;includes macros for outputting to the screen

.code
Fibonacci proc

MOV EAX, [EBP+8]
CMP EAX, 1
    JA Recurse
    MOV ECX, 1
    JMP exit

Recurse:
    DEC EAX
    MOV EDX, EAX
    PUSH EAX
    CALL Fibonacci
    ADD ESP, 4
    MOV EBX, ECX
    DEC EDX
    PUSH EDX
    CALL Fibonacci
    ADD ECX, EBX
exit:
ret
Fibonacci endp


.data


end
Run Code Online (Sandbox Code Playgroud)

此外,我已经推送了我用于在外部过程中将Fibonacci值转换为堆栈的数字.任何想法可能存在的想法?

assembly fibonacci

7
推荐指数
2
解决办法
4万
查看次数

加载和存储是否只有重新排序的指令?

我已经阅读了很多关于内存排序的文章,并且所有这些文章都只说CPU重新加载和存储.

CPU(我对x86 CPU特别感兴趣)是否仅重新排序加载和存储,并且不重新排序它具有的其余指令?

x86 cpu-architecture memory-barriers

6
推荐指数
2
解决办法
915
查看次数

使用环形总线拓扑的Intel CPU如何解码和处理端口I / O操作

我从硬件抽象级别理解端口I / O(即断言一个引脚,该引脚向总线上的设备指示该地址是端口地址,这在具有简单地址总线模型的早期CPU上是有意义的),但我不是真的确保在微体系结构上如何在现代CPU上实现它,尤其要确保端口I / O操作在环形总线上的显示方式。

在此处输入图片说明

首先。IN / OUT指令在哪里分配给保留站或加载/存储缓冲区?我最初的想法是,将在加载/存储缓冲区中分配它,并且内存调度程序将其识别出来,将其发送到L1d,指示它是端口映射操作。分配了一个行填充缓冲区,并将其发送到L2,然后发送到环网。我猜环上的消息有一些端口映射的指示器,只有系统代理才能接受它,然后它检查其内部组件并将端口映射的指示请求转发给它们。即PCIe根网桥将拾取CF8h和CFCh。我猜测DMI控制器是固定的,可以拾取将出现在PCH上的所有标准化端口,例如用于传统DMA控制器的端口。

hardware io x86 intel cpu-architecture

6
推荐指数
1
解决办法
201
查看次数

锁定指令是否在弱有序访问之间提供了障碍?

在x86上,除了原子操作之外,还提供了lock诸如lock cmpxchg提供屏障语义之类的前缀指令:对于回写内存区域的正常内存访问,读取和写入不是lock按照第3卷第8.2.2节中的预定指令重新排序的英特尔SDM:

无法使用I/O指令,锁定指令或序列化指令对读取或写入进行重新排序.

本节仅适用于回写内存类型.在同一个列表中,您会发现一个例外情况,它指出没有订购弱排序的商店:

  • 读取不会与其他读取重新排序.
  • 写入不会与较旧的读取重新排序.
  • 写入内存不会与其他写入重新排序,但以下情况除外: -

    使用非时间移动指令(MOVNTI,MOVNTQ,MOVNTDQ,MOVNTPS和MOVNTPD)执行的流存储(写入); 而且 -

    字符串操作(参见第8.2.4.1节).

注意,列表中的任何其他项目中的非时间指令没有例外,例如,在涉及锁定前缀指令的项目中.

在本指南的各种其他部分中,提到当使用弱有序(非时间)指令时,mfence和/或sfence指令可用于命令存储器.这些部分通常不提及lock- 作为替代的前缀指令.

所有这一切都让我不确定:do lock-prefixed指令提供了相同的完整屏障,它mfence提供了WB内存上的弱有序(非时间)指令之间的?同样的问题再次适用于WC内存的任何类型的访问.

x86 multithreading intel memory-model memory-fences

5
推荐指数
2
解决办法
253
查看次数

如何通过微体系结构实现障碍/栅栏以及获取,释放语义?

因此还有很多问题,例如https://mirrors.edge.kernel.org/pub/linux/kernel/people/paulmck/perfbook/perfbook.2018.12.08a.pdf和Preshing的文章如https:/ /preshing.com/20120710/memory-barriers-are-like-source-control-operations/及其整个系列文章就不同的障碍类型提供的排序和可见性保证方面抽象地讨论了内存排序。我的问题是,如何在x86和ARM微体系结构上实现这些障碍和内存排序语义?

对于商店-商店壁垒,好像在x86上,商店缓冲区保持商店的程序顺序并将它们提交到L1D(因此使它们以相同的顺序在全局可见)。如果存储缓冲区未排序,即未按程序顺序维护它们,那么如何实现存储障碍?它只是以这样的方式“标记”存储缓冲区,即在屏障提交之前将存储提交到缓存一致性域,然后在屏障之后提交?还是存储屏障实际上刷新了存储缓冲区并暂停了所有指令,直到刷新完成?可以同时实现吗?

对于负载障碍,如何防止负载重新排序?很难相信x86将按顺序执行所有加载!我假设加载可以乱序执行,但是可以按顺序提交/退出。如果是这样,如果一个cpu在2个不同的位置执行2次加载,那么一个加载如何确保它从T100中得到一个值,而下一个加载在T100上或之后得到它?如果第一个负载未命中高速缓存并正在等待数据,而第二个负载命中并获取其值,该怎么办。当负载1获得其值时,如何确保它获得的值不是来自该负载2的值的较新商店?如果负载可以无序执行,如何检测到违反内存排序的情况?

类似地,如何实现负载存储屏障(在x86的所有负载中都是隐含的)以及如何实现存储负载屏障(例如mfence)?即dmb ld / st和dmb指令在ARM上是如何微体系结构的?每个负载和每个存储区以及mfence指令在x86上如何进行微体系结构,以确保内存排序?

x86 x86-64 cpu-architecture memory-barriers micro-architecture

5
推荐指数
1
解决办法
72
查看次数

了解 PCI 地址映射

我正在研究 PC 架构,但觉得我没有掌握 PCI 地址的基础知识。

PCI中有三个地址空间:内存、输入输出端口和配置。我知道 CPU 可以使用不同的命令区分内存和端口,但是在 PCI 中会发生什么?我们在总线上有几个命令(读/写这些空间,中断处理等)。我认为在读取内存空间时,我们寻址到物理 RAM 地址,但在阅读了一些手册后,看起来我们寻址的是内部设备的内存。

  1. 为什么要使用内存映射?这是否意味着当某个程序写入映射到某个 PCI 设备的 RAM 地址时,它实际上是写入设备内存?为什么不使用标准IO口写?
  2. 如果需要,如何访问实内存?例如,如果设备想要将一些数据存储在 RAM 中,该请求将如何与“内存空间”访问区分开来?

peripherals io cpu-architecture pci-bus pci

2
推荐指数
1
解决办法
4721
查看次数

内存屏障是否既充当标记又充当指令?

我读过有关内存屏障如何工作的不同内容。

例如,用户Johan在这个问题中的回答说,内存屏障是 CPU 执行的指令。

虽然用户Peter Cordes在这个问题中的评论说了以下关于 CPU 如何重新排序指令的内容:

它的读取速度比执行速度快,因此它可以看到即将到来的指令的窗口。有关详细信息,请参阅 x86 标签 wiki 中的一些链接,例如 Agner Fog 的 microarch pdf,以及 David Kanter 对 Intel Haswell 设计的文章。当然,如果您只是用谷歌搜索“乱序执行”,您会找到您应该阅读的维基百科文章。

所以我根据上面的评论猜测,如果指令之间存在内存屏障,CPU将看到这个内存屏障,这导致CPU不会对指令重新排序,所以这意味着内存屏障是一个“标记”让CPU看到而不是执行。


现在我的猜测是,内存屏障既充当标记又充当 CPU 执行的指令。

对于标记部分,CPU 看到指令之间存在内存屏障,这导致 CPU 不会对指令进行重新排序。

至于指令部分,CPU会执行内存屏障指令,这会导致CPU做一些诸如刷新存储缓冲区之类的事情,然后CPU会继续执行内存屏障之后的指令。

我对么?

x86 assembly instruction-set cpu-architecture memory-barriers

2
推荐指数
1
解决办法
625
查看次数