相关疑难解决方法(0)

什么时候应该在C#中使用volatile关键字?

任何人都可以在C#中对volatile关键字提供一个很好的解释吗?它解决了哪些问题,哪些问题没有解决?在哪些情况下它会节省我使用锁定?

c# multithreading

290
推荐指数
8
解决办法
8万
查看次数

如何演示Java指令重新排序问题?

使用Java指令重新排序时,JVM会在编译时或运行时更改代码的执行顺序,这可能导致无关的语句无序执行.

所以我的问题是:

有人可以提供示例Java程序/片段,它可靠地显示指令重新排序问题,这也不是由其他同步问题(例如缓存/可见性或非原子r/w)引起的,就像我在这样的演示中尝试失败一样在我之前的问题中)

为了强调,我不是在寻找理论重新排序问题的例子.我正在寻找的是通过查看正在运行的程序的错误或意外结果来实际演示它们的方法.

除了一个错误的行为示例,只显示在一个简单程序的程序集中发生的实际重新排序也可能是好的.

java multithreading compiler-optimization instruction-reordering

37
推荐指数
2
解决办法
837
查看次数

生产者 - 消费者在超兄弟姐妹与非兄弟姐妹之间共享内存位置的延迟和吞吐量成本是多少?

单个进程中的两个不同线程可以通过读取和/或写入来共享公共存储器位置.

通常,这种(有意)共享是使用lockx86上的前缀使用原子操作实现的,该前缀对于lock前缀本身(即,无竞争成本)具有相当广为人知的成本,并且当实际共享高速缓存行时还具有额外的一致性成本(真或共享).

在这里,我对生产 - 消费者成本感兴趣,其中单个线程P写入内存位置,另一个线程`C从内存位置读取,都使用普通读取和写入.

在同一个套接字上的不同内核上执行此类操作的延迟和吞吐量是多少,并且在最近的x86内核上在同一物理内核上执行兄弟超线程时进行比较.

在标题中,我使用术语"超级兄弟"来指代在同一核心的两个逻辑线程上运行的两个线程,以及核心间兄弟,以指代在不同物理核心上运行的两个线程的更常见情况.

concurrency performance x86 hyperthreading

17
推荐指数
2
解决办法
846
查看次数

相关负载在CPU中重新排序

我一直在阅读内存障碍:软件黑客的硬件视图,这是Paul E. McKenney的一篇非常受欢迎的文章.

本文强调的一点是,像Alpha这样非常微弱有序的处理器可以重新排序依赖负载,这似乎是分区缓存的副作用

论文摘录:

1 struct el *insert(long key, long data)
2 {
3     struct el *p;
4     p = kmalloc(sizeof(*p), GPF_ATOMIC);
5     spin_lock(&mutex);
6     p->next = head.next;
7     p->key = key;
8     p->data = data; 
9     smp_wmb();
10    head.next = p;
11    spin_unlock(&mutex);
12 }
13
14 struct el *search(long key)
15 {
16     struct el *p;
17     p = head.next;
18     while (p != &head) {
19         /* BUG ON ALPHA!!! */
20         if (p->key …
Run Code Online (Sandbox Code Playgroud)

synchronization locking cpu-architecture lock-free memory-barriers

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

预取指令是否需要在退出之前返回结果?

在最近的Intel和AMD CPU上,执行的预取指令是否仍然可以退出,但是请求的行还没有到达指定的缓存级别?

也就是说,预取"阻塞"的退出是因为它似乎是负载,还是非阻塞?

performance x86 prefetch

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

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

因此还有很多问题,例如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
查看次数

乱序执行会导致推测性内存访问吗?

当无序处理器遇到类似的东西时

LOAD R1, 0x1337
LOAD R2, $R1
LOAD R3, 0x42
Run Code Online (Sandbox Code Playgroud)

假设所有访问都会导致高速缓存未命中,处理器是否可以在询问内容$ R1甚至0x1337之前询问内存控制器0x42的内容?如果是这样,假设访问$ R1将导致异常(例如,分段错误),我们可以认为0x42是以推测方式加载的,对吗?

顺便说一句,当一个加载存储单元向内存控制器发送请求时,它是否可以在收到前一个请求之前发送第二个请求?

我的问题并不针对任何架构.欢迎与任何主流架构相关的答案.

architecture x86 arm powerpc sparc

4
推荐指数
1
解决办法
1674
查看次数

是否会在其他线程中始终以相同顺序看到对不同线程中不同位置的两次原子写操作?

与我之前的问题类似,请考虑以下代码

-- Initially --
std::atomic<int> x{0};
std::atomic<int> y{0};

-- Thread 1 --
x.store(1, std::memory_order_release);

-- Thread 2 --
y.store(2, std::memory_order_release);

-- Thread 3 --
int r1 = x.load(std::memory_order_acquire);   // x first
int r2 = y.load(std::memory_order_acquire);

-- Thread 4 --
int r3 = y.load(std::memory_order_acquire);   // y first
int r4 = x.load(std::memory_order_acquire);
Run Code Online (Sandbox Code Playgroud)

怪异的结果 r1==1, r2==0,并r3==2, r4==0有可能在C ++ 11内存模型下,这种情况下?如果我要全部替换std::memory_order_acq_rel成该std::memory_order_relaxed怎么办?

在x86上,这样的结果似乎是被禁止的,请参见此SO问题,但我一般是在询问C ++ 11内存模型。

奖励问题:

我们都同意,与std::memory_order_seq_cst怪异的结果不会在C ++ 11被允许。现在,赫伯·萨特(Herb Sutter)在他著名的- …

c++ concurrency memory-model c++11 stdatomic

4
推荐指数
3
解决办法
540
查看次数

缓存一致性文献一般只涉及存储缓冲区而不是读取缓冲区。然而,不知何故,两者都需要?

在阅读一致性模型(即 x86 TSO)时,作者通常会使用包含大量 CPU、相关存储缓冲区和私有缓存的模型。

如果我的理解是正确的,存储缓冲区可以被描述为队列,CPU 可以在其中放置他们想要提交到内存的任何存储指令。因此,顾名思义,它们是store缓冲区。

但是当我阅读这些论文时,他们倾向于谈论加载和存储的交互,诸如“稍后加载可以通过较早存储”之类的陈述有点令人困惑,因为它们几乎似乎在谈论存储缓冲区将同时具有加载和存储,当它没有时 - 对吗?

所以也必须有一个他们没有(至少明确地)谈论的负载存储。另外,这两者必须以某种方式同步,所以两者都知道什么时候可以从内存加载并提交到内存——或者我是否遗漏了什么?

任何人都可以对此有所了解吗?

编辑:

让我们看一下“内存一致性和缓存一致性入门”中的一段:

为了理解 TSO 中原子 RMW 的实现,我们将 RMW 视为紧跟在存储之后的负载。由于 TSO 的排序规则,RMW 的负载部分无法通过较早的负载。乍一看,RMW 的加载部分可能会传递写入缓冲区中较早的存储,但这是不合法的。如果 RMW 的加载部分通过较早的存储,则 RMW 的存储部分也必须通过较早的存储,因为 RMW 是原子对。但是由于在 TSO 中不允许 store 相互传递,因此 RMW 的负载部分也不能通过较早的 store

进一步来说,

由于 TSO 的排序规则,RMW 的负载部分无法通过较早的负载。乍一看,RMW 的加载部分可能会传递写入缓冲区中较早的存储

所以他们指的是在写入缓冲区中相互交叉的负载/存储(我认为这与存储缓冲区相同?)

谢谢

concurrency x86 cpu-architecture memory-model

4
推荐指数
1
解决办法
235
查看次数

从寄存器移动到频繁访问的变量时性能意外降低

我正在使用以下示例了解缓存的工作原理:

\n
#include <stdio.h>\n#include <stdint.h>\n#include <stdlib.h>\n\ntypedef uint32_t data_t;\nconst int U = 10000000;   // size of the array. 10 million vals ~= 40MB\nconst int N = 100000000;  // number of searches to perform\n\nint main() {\n  data_t* data = (data_t*) malloc(U * sizeof(data_t));\n  if (data == NULL) {\n    free(data);\n    printf("Error: not enough memory\\n");\n    exit(-1);\n  }\n\n  // fill up the array with sequential (sorted) values.\n  int i;\n  for (i = 0; i < U; i++) {\n    data[i] = i;\n  }\n\n  printf("Allocated array of …
Run Code Online (Sandbox Code Playgroud)

c assembly caching x86-64 perf

3
推荐指数
1
解决办法
138
查看次数

Intel X86如何实现全店排序

由于其 TSO 内存模型,X86 保证所有商店的总顺序。我的问题是是否有人知道这是如何实际实施的。

我对所有 4 个围栏是如何实现的印象很好,所以我可以解释如何保留本地秩序。但是 4 个栅栏只会给 PO;它不会给您 TSO(我知道 TSO 允许旧商店跳到新负载前面,因此只需要 4 个围栏中的 3 个)。

单个地址上所有内存操作的总顺序是一致性的责任。但我想知道英特尔(特别是 Skylake)如何在多个地址的商店上实现总订单。

x86 intel cpu-architecture memory-barriers micro-architecture

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

是否需要内存屏障是因为CPU乱序执行还是因为缓存一致性问题?

我想知道为什么需要内存屏障,我已经阅读了一些关于这个主题的文章。
有人说这是因为cpu乱序执行,而另一些人说这是因为缓存一致性问题,存储缓冲区和无效队列导致。
那么,需要内存屏障的真正原因是什么?cpu乱序执行或者缓存一致性问题?或两者?cpu乱序执行和缓存一致性有关系吗?x86和arm有什么区别?

x86 arm cpu-architecture memory-barriers cpu-cache

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

Java指令重排序和CPU内存重排序

这是一个后续问题

如何演示Java指令重排序问题?

有很多文章和博客提到 Java 和 JVM 指令重新排序,这可能会导致用户操作中出现反直觉的结果。

当我要求演示 Java 指令重新排序导致意外结果时,有几条评论说,更普遍的关注领域是内存重新排序,并且很难在 x86 CPU 上进行演示。

指令重新排序只是内存重新排序、编译器优化和内存模型等更大问题的一部分吗?这些问题真的是 Java 编译器和 JVM 特有的吗?它们是否特定于某些 CPU 类型?

java cpu-architecture memory-barriers instruction-reordering

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