我读过这个主题:C#线程安全快速(est)计数器,并在我的并行代码中实现了这个特性。据我所知,这一切都很好,但它大大增加了处理时间,大约10%。
这让我有点担心,我认为问题在于我做了大量相对便宜的产品(
现在,我看不到解决的办法,但也许我错过了一些明显的东西。我甚至在考虑使用n个计数器(对应于并行化程度),然后在特定的核上增加每个计数器,但这似乎不可行(检测我在哪个核上可能会更昂贵,更不用说复杂的if/then/else结构和混乱的执行管道)。有没有办法打破这个怪兽?:)
我想我会对高速缓存一致性和LOCK
前缀在英特尔架构中的作用进行一些澄清。由于评论太长,也回答了您提出的一些问题,我认为发布作为答案是合适的。
在MESI高速缓存一致性协议中,对缓存行的任何写入都会导致状态更改为独占,无论您是否使用LOCK
前缀。因此,如果两个处理器都重复访问同一个缓存行,并且至少有一个处理器正在进行写入,那么处理器在访问它们共享的行时会遇到缓存行未命中。而如果他们都只从该行读取,那么他们就会有缓存行命中,因为他们都可以将私有L1缓存中的行保持在共享状态。
LOCK
前缀的作用是限制处理器在等待锁定的指令完成执行时可以做的推测性工作的数量。《英特尔64和IA-32体系结构软件开发人员手册》第8.1.2节说:
锁定操作是相对于所有其他内存操作和所有外部可见事件的原子操作。只有指令获取和页表访问才能传递锁定的指令。锁定指令可用于同步一个处理器写入和另一个处理器读取的数据。
在正常情况下,处理器能够在等待解决缓存未命中的同时推测地执行指令。但是LOCK
前缀阻止了这一点,并且基本上会暂停管道,直到锁定的指令完成执行。
来自同一缓存线上多个内核的操作在硬件中相互竞争。这适用于锁定和常规内存访问。这是一个真正的问题。当添加更多内核时,争用访问根本不会扩展。缩放通常是硬负数。
您需要使用多个缓存线,每个核心大部分时间都使用自己的缓存线。
你可以使用ThreadLocal
请注意,每个内核使用一个计数器并不重要。每线程就足够了,因为与增量操作相比,时间量子非常长。一些糟糕的访问不是性能问题。
一个更快的选择是使用
Holder[]
。每个线程绘制一次随机数组索引,然后访问该持有人对象。数组索引比线程本地访问更快。如果您使用的持有人实例的数量比线程的数量大得多(10倍),则几乎没有争用。大多数写入将使用相同的已缓存行。
你可以使用
列表代替随机索引
如何在C#中获得性能最佳的线程安全计数器? 这很简单: 但有更快的替代方案吗?
问题内容: 我从一个非常简单的多线程示例开始。我试图做一个线程安全的计数器。我想创建两个线程,使计数器间歇地增加到1000。以下代码: 据我所知,while循环现在意味着只有第一个线程才能访问计数器,直到达到1000。输出: 我该如何解决?如何获得共享计数器的线程? 问题答案: 两个线程都可以访问您的变量。 您看到的现象称为线程饥饿。输入代码的受保护部分后(很抱歉,我之前错过了它),其他线程将需要
问题内容: 我在某个字段上有一个带有getter 和setter 的类,例如field 说一个类的对象。 在这里synchronized– 不是。 我正在从多个线程中更新值。每个线程都在获取值,并进行适当设置。线程不会以任何方式共享任何其他资源。 在每个线程中执行的代码如下。 该方法只是对通过传递给它的参数从构造函数内部更新的成员调用上述方法: 当我按较大的顺序运行此线程时,线程之间的交错并不多-
我需要实现线程安全的集群范围计数器map,所以我使用Hazelcast使它成为集群范围的,但不知道如何使它成为线程安全的,我尝试使用AtomicInteger,但看起来像是当一个线程反序列化AtomicInteger以进行增量时,其他线程可能会进行增量并将其放回map中。所以你能给我提点建议吗?某种最佳实践?我认为我可以使用分布式锁实现它,但不确定这是最好的解决方案。
问题内容: 我正在制作一个需要一堆日记条目并计算总和的应用程序。 下面的方法是在有 多个线程 调用该方法时是线程/并发安全的。我想确保每个电话都能正确更新总数。 如果不安全,请说明为确保线程安全我该怎么做。 我需要获取/放置还是有更好的方法? 非常感谢! 更新: 谢谢大家的回答,我已经知道上面的代码 不是线程安全的 。 感谢Vint建议使用替代。我以前用来保存整数和,我想知道BigDecimal是
问题内容: 我的应用程序中有一种情况,每次用户角色更改时,我都需要重新加载菜单(一个用户可以在多家公司中担任角色)。 我想知道什么是解决此问题的最佳方法。 目前,我正在执行以下操作: 简单地将用户重定向到菜单加载视图,然后在角色完成加载后从那里返回菜单视图。我把它包装在一个函数中: 在我想重新加载菜单的任何情况下都可以调用它。 我想知道是否可以通过从$ rootScope上的服务广播此事件,然后在