英文:
Go atomic and memory order
问题
我正在将一个无锁队列从C++11移植到Go语言,并遇到了以下内容:
currentRead := atomic.LoadUint64(&q.writeIndex)
在移植后,我进行了基准测试,发现只使用LoadUint64
似乎按预期工作,但速度慢了几个数量级。我想知道这些特殊操作对性能有多大影响。
在Go语言中,没有与C++中的这些操作完全等价的操作。Go语言的原子操作提供了一些基本的原子操作函数,如LoadUint64
和StoreUint64
,但没有提供像C++中的memory_order_relaxed
、memory_order_acquire
和memory_order_release
这样的精确控制。
在Go语言中,原子操作的语义是强一致性的,即保证所有的内存访问都按照程序的顺序执行,不会发生重排序。这种强一致性的语义通常可以满足大多数情况下的需求。
如果你需要更细粒度的内存访问控制,可能需要使用其他的同步机制,如互斥锁或条件变量,来实现类似的功能。具体的实现方式取决于你的具体需求和代码结构。
英文:
I am porting a lock free queue from c++11 to go and i came across things such as
auto currentRead = writeIndex.load(std::memory_order_relaxed);
and in some cases std::memory_order_release
and std::memory_order_aqcuire
also the equivelent for the above in c11 is something like
unsigned long currentRead = atomic_load_explicit(&q->writeIndex,memory_order_relaxed);
the meaning of those is described here
is there an equivalent to such thing in go or do i just use something like
var currentRead uint64 = atomic.LoadUint64(&q.writeIndex)
after porting i benchmarked and just using LoadUint64 it seems to work as expected but orders of magnitude slower and i wonder how much effect dose those specialized ops have on performance.
- further info from the link i attached
> memory_order_relaxed:Relaxed operation: there are no synchronization
> or ordering constraints, only atomicity is required of this operation.
>
>
> memory_order_consume:A load operation with this memory order performs
> a consume operation on the affected memory location: no reads in the
> current thread dependent on the value currently loaded can be
> reordered before this load. This ensures that writes to data-dependent
> variables in other threads that release the same atomic variable are
> visible in the current thread. On most platforms, this affects
> compiler optimizations only.
>
> memory_order_acquire:A load operation with this memory order performs the acquire operation on the affected memory location: no
> memory accesses in the current thread can be reordered before this
> load. This ensures that all writes in other threads that release the
> same atomic variable are visible in the current thread.
>
>memory_order_release:A store operation with this memory order performs the release operation: no memory accesses in the current
> thread can be reordered after this store. This ensures that all writes
> in the current thread are visible in other threads that acquire or the
> same atomic variable and writes that carry a dependency into the
> atomic variable become visible in other threads that consume the same
> atomic.
答案1
得分: 7
你需要阅读《Go内存模型》(The Go Memory Model)。
你会发现,Go语言没有像C++那样的控制能力——在你的帖子中,并没有直接翻译C++的特性。这是Go语言作者的一个有意设计决策——Go的座右铭是“不通过共享内存来通信,而是通过通信来共享内存”。
假设标准的Go通道对你想要做的事情不够好,对于每个内存访问,你有两个选择:使用sync/atomic中的工具或不使用。你是否需要使用它们将取决于对Go内存模型的仔细阅读和对代码的分析,这只有你自己能做。
英文:
You need to read The Go Memory Model
You'll discover that Go has nothing like the control that you have in C++ - there isn't a direct translation of the C++ features in your post. This is a deliberate design decision by the Go authors - the Go motto is Do not communicate by sharing memory; instead, share memory by communicating.
Assuming that the standard go channel isn't good enough for what you want to do, you'll have 2 choices for each memory access, using the facilities in sync/atomic or not, and whether you need to use them or not will depend on a careful reading of the Go Memory Model and analysis of your code which only you can do.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论