这是对Thread.MemoryBarrier()的正确使用吗?
假设我的字段控制某些循环的执行: private static bool shouldRun = true; 我有一个线程,其中有类似的代码: while(shouldRun) { // Do some work .... Thread.MemoryBarrier(); } 现在,另一个线程可能将shouldRun设置为false,而无需使用任何同步机制. 据我了解thread.memorybarrier(),在内部进行此呼叫会阻止我的工作线程获得shouldRun的缓存版本,并有效防止无限循环发生. 我对线程的理解是正确的吗?一旦shouldRun设置为false,循环将停止. 解决方案 这是thread.memorybarrier()的正确用途吗? 否.假设一个线程在之前设置了flag 循环甚至开始执行.使用标志的缓存值仍然可以执行一次循环.那是正确的吗?对我来说似乎不正确.我希望,如果我在第一次执行循环之前设置标志
4 2024-01-07
编程技术问答社区
.NET易失性.读/写和互锁的范围
我已经阅读了,例如,想象我有一个数组和一个计数器. long counter = 0; var values = new double[1000000]; values[42] = 3.1415; // Is this line needed instead of simple assignment above, // or the implicit full-fence of Interlocked will guarantee that // all threads will see the values[42] after interlocked increment? //Volatile.Write(ref values[42], 3.1415); Interlocked.Increment(ref counter); 确实可以互锁的增量保证相同的结果,就像我使用Volatile.Write(ref values[42], 3.1415);而不是values[42]
2 2024-01-06
编程技术问答社区
在.NET中何时使用锁与MemoryBarrier
在.net中lock关键字是Monitor.Enter和Monitor.Exit周围的句法糖,因此您可以说此代码 lock(locker) { // Do something } 与 相同 Monitor.Enter(locker); try { // Do Something } finally { Monitor.Exit(locker); } 但是,.NET框架还包括以类似方式工作的MemoryBarrier类 Thread.MemoryBarrier(); //Do something Thread.MemoryBarrier(); 我很困惑,就像我想在lock/Monitor版本上使用Thread.MemoryBarrier时一样?我被 /p> 据我所知,可见的差异不需要一个锁定对象,我猜想使用Monitor您可以在单个线程上MemoryBarrier上的线程进行一些操作. 我的直觉告诉我,另一个关键区别是MemoryBarrier仅
0 2024-01-03
编程技术问答社区
线程安全类在其构造函数的末尾是否应该有一个内存屏障?
实现旨在使用线程安全的类时,我是否应该在其构造函数的末端包括一个内存屏障,以确保在访问它们之前已完成任何内部结构?还是消费者有责任在使实例可用于其他线程之前插入内存屏障? 简化的问题: 下面的代码中是否存在种族危害,由于初始化和线程安全类的访问之间缺乏记忆障碍,因此可能会产生错误的行为?还是线程安全类本身应该保护这种情况? ConcurrentQueue queue = null; Parallel.Invoke( () => queue = new ConcurrentQueue(), () => queue?.Enqueue(5)); 请注意,该程序可以什么都不招募,就像第二代表在第一个代表之前执行的那样. (无效的操作员?.在这里预防A NullReferenceException.无限循环,或者在内部结构上造成种族危害引起的任何其他奇怪的事情. 详细的问题: 具体地说,想象一下我正在为队列实现一个简单的线程包
0 2024-01-02
编程技术问答社区
为什么我们需要Thread.MemoryBarrier()?
在"简介中的C#4"中,作者表明该类有时可以在没有MemoryBarrier的情况下写0,尽管我不能在我的core2duo中复制: public class Foo { int _answer; bool _complete; public void A() { _answer = 123; //Thread.MemoryBarrier(); // Barrier 1 _complete = true; //Thread.MemoryBarrier(); // Barrier 2 } public void B() { //Thread.MemoryBarrier(); // Barrier 3 if (_complete) { //Thread.MemoryBarrier(
2 2024-01-02
编程技术问答社区
存储器障碍的跨度/累积性特性是如何在微观架构上实现的?
我一直在阅读有关X86内存模型的工作原理以及X86上的障碍指令的重要性,并与其他架构(例如ARMV8)进行了比较.在X86和ARMV8架构中,似乎(毫无意义)的记忆模型尊重传递性/累积性,即,如果CPU 1通过CPU0看到商店,而CPU2则通过CPU1看到CPU1,只有CPU1 SEE CPU0商店才能发生CPU1.然后,CPU2还必须查看CPU0的商店.我指的是保罗·麦肯尼(Paul McKenney)著名论文第6.1节中的示例1和2/images/hwviewforswhackers.pdf" rel =" noreferrer"> http://www.puppetmastertrading.com/images/hwviewforswhackers.pdf ).如果我理解正确的话,X86使用商店队列的(或商店订单缓冲区)在全球可见之前(即写入L1D)之前订购商店(以及其他微拱优化).我的问题是X86 Arch(和其他Arch的)如何实现(在微构造上)传递性属性?商店队列确保特定的
0 2023-12-16
编程技术问答社区
C11 原子获取/释放和x86_64缺乏负载/存储的一致性?
我在C11标准的第5.1.2.4节中挣扎,特别是发行/获取的语义.我注意到, ...释放语义可以通过以程序顺序进行任何读取或写入操作的任何读取或写入操作的写入释放的记忆重新排序. 因此,以下内容: typedef struct test_struct { _Atomic(bool) ready ; int v1 ; int v2 ; } test_struct_t ; extern void test_init(test_struct_t* ts, int v1, int v2) { ts->v1 = v1 ; ts->v2 = v2 ; atomic_store_explicit(&ts->ready, false, memory_order_release) ; } extern int test_thread_1(test_struct_t* ts, int v2) { int v1 ; while (atomic_load_e
12 2023-12-16
编程技术问答社区
障碍/栅栏和获取、释放语义是如何在微架构上实现的?
很多问题和文章/书籍,例如 https://mirrors.gend.kernel.org/pub/linux/kernel/kernel/people/paulmck/pefbook/perfbook.2018.12.08a.pdf =" https://preshing.com/20120710/memory-barriers-are-like-source-control-operations/" -source-control-operations/以及他的整个文章,就不同的障碍类型提供的订购和可见性保证,抽象地谈论记忆订购.我的问题是,这些障碍和记忆订购语义是如何在X86上实现的,并且ARM Micro Architecturely in 是如何实现的? 对于商店商店的障碍,似乎在x86上,商店缓冲区维护了商店的程序顺序,并将其提交为L1D(因此,以相同的顺序使它们在全球范围内可见).如果未订购商店缓冲区,则IE不会以程序顺序维护它们,如何实现商店障碍?它只是"标记"了
2 2023-12-16
编程技术问答社区
在x86/x86_64处理器上使用LFENCE指令是否有意义?
经常在互联网中发现LFENCE在处理器x86中没有任何意义,即它无能为力,所以MFENCE我们绝对可以无痛地使用SFENCE,因为MFENCE = SFENCE + = SFENCE + NOP = SFENCE. 但是,如果LFENCE没有意义,那么为什么我们有四种方法可以在x86/x86_64中保持顺序一致性: LOAD(无围栏)和STORE + MFENCE LOAD(无围栏)和LOCK XCHG MFENCE + LOAD和STORE(无围栏) LOCK XADD(0)和STORE(无围栏) 从这里取: http://www.cl.cl.cl.cam.ac.ac.uk/〜pes20/cpp/cpp0xmappings.html 以及底部第34页的Herb Sutter的表演:如果LFENCE什么都没做,则方法(3)将具有以下含义:SFENCE + LOAD and STORE (without fence),但是在SFENCE + LOAD and
8 2023-12-16
编程技术问答社区
为什么SFENCE+LFENCE等同于MFENCE(或不是?
正如我们从先前对在处理器x86/x86_64中有任何有意义的指令?我们不能使用SFENCE而不是MFENCE进行顺序一致性. 那里的答案表明,MFENCE = SFENCE+LFENCE,即LFENCE做的事情没有,我们将无法提供顺序的一致性. LFENCE无法重新排序: SFENCE LFENCE MOV reg, [addr] - to-> MOV reg, [addr] SFENCE LFENCE 例如,由MOV [addr], reg LFENCE的重新排序 - > LFENCE MOV [addr], reg由机制提供 - 商店缓冲区,它重新订购 - 加载性能提高,而beacause LFENCE不能阻止它.和SFENCE 禁用此机制. 哪种机制可以禁用LFENCE使不可能的重新排序(x86没有机制 - 无效-Queue)? ,并且仅在理论上还是在现实中重新排序SFENCE MOV reg, [addr] - > MOV reg, [
4 2023-12-16
编程技术问答社区
如何才能体验到 "LFENCE或SFENCE无法通过早期读/写"?
我正在做有关功能安全的事情.我需要验证一些X86 CPU指令,例如Lfence,Sfence和Mfence. 现在,我可以根据英特尔SDM第8.2.3.4章体验Mfence. "xor %0, %0\n\t " "movl $1, %1\n\t " "mfence\n\t " "movl %2, %0\n\t " : "=r"(r1), "=m" (X) : "m"(Y) : "memory"); "xor %0, %0\n\t " "movl $1, %1\n\t " "mfence\n\t " "movl %2, %0\n\t
0 2023-12-15
编程技术问答社区
_mm_sfence固有和sfence指令之间有什么关系?
我正在尝试非时空指令,并且已经熟悉了使用普通负载/商店的栅栏. intel定义了与非时空操作相关的固有的_mm_sfence,该手册将其定义为: 保证在任何后续商店之前在全球范围内都可以看到所有上述商店. 我对此操作有一些疑问. 这只是插入Sfence指令吗?如果没有,这将转化为什么? 如果这不仅是Sfence,Sfence指令是否还具有非阶乘商店的订购保证? 解决方案 _mm_sfence固有的作用两件事: 插入SFENCE指令. 根据编译器的不同,它插入编译器写障碍,以使编译器不会在程序顺序上重新排序任何内在的内存.在GCC,MSVC和ICC中就是这种情况.虽然不确定叮当声,但很可能也是如此.
6 2023-12-15
编程技术问答社区
_mm_mfence()函数做什么
查看Intel Interins文档, _mm_mfence 的概述如下 对本说明之前发出的所有负载中的内存和商店到内存指令执行序列化操作.确保按程序顺序进行的每个内存访问在任何内存指令之前都可以看到内存围栏指令. . 相应的mfence> ASM手册相似. 似乎有很多术语,我听不懂任何人都可以清除_mm_mfence实际做什么 我试图将其搜索到Google上,但他们不是不错的文档或其他提出的问题. 解决方案 固有的固有性是针对编译时间和运行时间重新排序的全部障碍,包括阻止 storeload重新排序,唯一的X86允许在运行时允许 - https://preshing.com/20120515/memory-reordering-cought-cought-cought-in-the-ach-act/具有mfence的ASM演示行动. (x86的ASM内存模型是程序订单,以及带有商店 - 往返的商店逃避者,因此获取/释放是免费的,只有顺序一致性才需要更强
6 2023-12-15
编程技术问答社区
为什么 "movnti "后面有一个 "sfence "来保证持久的排序?
sfence sfence防止NT商店从商店的buffer forefter of Store Buffer. Sfence本身. 商店缓冲区. 因此,Sfence只能保证输入LFB的数据的订购. 例如, movnti; sfence; movnti to another address; 这里的Sfence只能保证第一个NT商店将比下一个商店提前投入LFB.但是,由于LFB挥发了,因此数据尚未持续存在.输入LFB的数据会以输入的顺序持续吗? 解决方案 sfence确保在程序顺序上所有较早的商店都可以在全球范围内观察到,然后在程序顺序上以较晚的方式进行全球观察.这里的商店包括数据存储UOPS,clflush,clflushopt,clwb,movdiri和movdir64b. . GO的点取决于以下所有内容: 操作类型, 存在非时空提示, 目标内存位置的内存类型 映射到目标内存地址的设备, 微体系结构. 例如,在现代的Intel
0 2023-12-15
编程技术问答社区
在C++中用一个内存屏障防止凭空取值
让我们考虑C ++中的以下两线并发程序: x,y是Globals,r1,r2是螺纹 - 本地,store和load to int是原子. 内存模型= C ++ 11 int x = 0, int y = 0 r1 = x | r2 = y y = r1 | x = r2 允许编译器将其编译为: int x = 0, int y = 0 r1 = x | r2 = 42 y = r1 | x = r2 | if(y != 42) | x = r2 = y ,虽然线程一致,但它可能会导致狂野的结果,因为该程序的执行可能会导致(x, y) = (42, 42) 它被称为从稀薄的空气中值问题.它存在,我们必须忍受. 我的问题是:记忆屏障是否阻止编译器进行野生优化,从而导致薄式空气值? 例如: [fence] = atomic_thread_fence(memory_order
0 2023-12-15
编程技术问答社区
放宽内存排序时,C++的延迟会增加
我在Windows 7 64位,VS2013(X64 Release Build)实验内存订购.我想使用最快的同步共享对容器的访问.我选择了原子比较. 我的程序产生了两个线程.作者推到向量,读者检测到这一点. 最初我没有指定任何内存订购,所以我假设它使用memory_order_seq_cst? 使用memory_order_seq_cst延迟为340-380个周期 尝试提高性能,我使商店使用memory_order_release使用memory_order_acquire. . 然而,潜伏期增加到约1,940个周期 我误解了什么吗?下面的完整代码. 使用默认值memory_order_seq_cst: #include #include #include #include std::atomic _lock{ false }; std::vector
0 2023-12-15
编程技术问答社区
为什么这个`std::atomic_thread_fence`可以工作
首先,我想列出有关此的一些承诺,如果我错了,请纠正我. x86中的A MFENCE可以确保完整的障碍 顺序一致性可防止商店商店,商店载荷,负载商店和Load-Load 的重新排序 这是根据 wikipedia . std::memory_order_seq_cst不能保证防止存储载荷重新订购. 这是根据 Alex的答案",可以将负载与较早的商店重新排序到不同的位置"(对于X86),并且不会始终添加Mfence. A std::memory_order_seq_cst是否表示顺序矛盾?根据第2/3点,对我来说似乎不正确. std::memory_order_seq_cst仅在 时才表示顺序矛盾 至少一个显式MFENCE添加到LOAD或STORE 负载(无栅栏)和锁定XCHG 锁定XADD(0)和存储(无围栏) 否则可能会有可能的再折叠. 根据 @lwimsey的评论,我在这里犯了一个错误,如果LOAD和STORE都是memory_orde
4 2023-12-15
编程技术问答社区
(持久性)将英特尔非时间性存储排序到同一缓存行中
非时空存储(例如Movnti),同一线程发行的同一缓存线,以程序顺序达到内存? 因此,对于具有NVRAM的系统(例如带有Intel 3D Xpoint NVRAM的Intel Cascade Lake处理器),如果发生崩溃,则缺乏重新排序可以保证该写作的A prefix 相同的缓存线盛行? 解决方案 假设非时空商店的已解决的存储器类型是WC(或WC+),这是我认为您要问的,答案大多不在Intel和AMD处理器上. 对于Intel处理器,Intel SDM V2第11.3.1节中的某些语句指定了至少一个WC Buffer在MicroArchitecturs上写下兼击的行为. 驱逐WC缓冲区的协议取决于实现 并且不应由软件依靠系统内存相干性. 这是一个一般性陈述,说WC驱逐和交易的原因是驱逐WC缓冲液的实现依赖性.但是手册中的不同位置有特定的陈述. 同样[喜欢在P6上],对于最新的处理器开始 基于Intel Netburst微体系结构,完整的WC缓冲区将
8 2023-12-15
编程技术问答社区
假设没有非时间指令,"xchg "是否包含了 "mfence"?
我已经看过这个答案和此答案,但在没有非颞指令的假设下,似乎都没有明确和明确地明确mfence和xchg. . Intel 教学对于xchg> 此说明对于实现流程同步的信号量或类似的数据结构很有用,进一步参考了卷3A .该引用陈述以下内容. 对于P6家庭处理器,锁定操作序列化 出色的负载和商店运营(也就是说,等待它们 完全的).该规则对于奔腾4和英特尔Xeon也是如此 处理器,一个例外.负载操作弱参考 有序的内存类型(例如WC内存类型)可能不是 序列化. mfence文档要求以下内容. 在所有负载中执行序列化操作, 在Mfence之前发布的商店到存储器说明 操作说明.这种序列化操作确保了每个负载和 在程序中的MFENCE指令之前的商店说明 订单在任何负载或商店指令之前都在全球可见 这遵循MFENCE指令. 1 Mfence指令是 关于所有负载和存储说明的订购 说明,任何LFENCE和SFENCE指示以及任何序列化 说明(例如CPUID指令). Mfence没有 序
0 2023-12-15
编程技术问答社区
内存围栏是否会阻塞多核CPU中的线程?
我正在阅读Intel指导集指南64-IA-32 指南 在内存围栏上了解一个想法.我的问题是,为了确保所有商店操作在全球范围内都可见,多核CPU公园是否甚至在其他内核上运行的所有线程,直到达到缓存相干性达到? 解决方案 屏障不会使其他线程/内核等待.他们在当前线程中进行一些操作,具体取决于它是什么样的障碍.非记忆说明不一定会阻止非记忆说明的执行. 屏障甚至不会使您的负载/商店更快地看到其他线程. CPU核心已经从商店缓冲区尽可能快地到L1D缓存. (遵循了所有必要的MESI相干性规则,X86的强内存模型仅允许商店即使没有障碍也可以在程序顺序上投入). 障碍不一定订购指令执行,它们订购了全球可见性,即商店缓冲区的远端发生了什么. mfence以使整个核心停滞直至存储缓冲液排水的方式实现.看到我的答案 是唯一的说明,是唯一的说明重新排序?以获取详细信息;这种额外的放缓是修复勘误.但是lock ed操作和xchg在Skylake上不像那样;它们是充分的内存障碍,但仍然允
8 2023-12-15
编程技术问答社区