函数调用是否是现代平台的有效内存屏障? [英] Is function call an effective memory barrier for modern platforms?

查看:124
本文介绍了函数调用是否是现代平台的有效内存屏障?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我审阅的代码库中,我发现了以下成语.

In a codebase I reviewed, I found the following idiom.

void notify(struct actor_t act) {
    write(act.pipe, "M", 1);
}
// thread A sending data to thread B
void send(byte *data) {
    global.data = data;
    notify(threadB);
}
// in thread B event loop
read(this.sock, &cmd, 1);
switch (cmd) {
    case 'M': use_data(global.data);break;
    ...
}

保留它",我对我的团队的资深成员说,这里没有内存障碍!您不能保证将global.data从高速缓存刷新到主内存.如果线程A并且线程B将在两个不同的处理器中运行-该方案可能会失败."

"Hold it", I said to the author, a senior member of my team, "there's no memory barrier here! You don't guarantee that global.data will be flushed from the cache to main memory. If thread A and thread B will run in two different processors - this scheme might fail".

高级程序员咧开嘴笑着,慢慢地解释着,好像在向他的五岁男孩解释如何系鞋带:听小男孩,我们在这里看到了许多与线程相关的错误,包括高负载测试和真实的客户. ",他停下来to了long那长长的胡须,但我们从来没有遇到过这样的习惯."

The senior programmer grinned, and explained slowly, as if explaining his five years old boy how to tie his shoelaces: "Listen young boy, we've seen here many thread related bugs, in high load testing, and in real clients", he paused to scratch his longish beard, "but we've never had a bug with this idiom".

但是,它在书中说……"

"But, it says in the book..."

安静!",他迅速向我安静,也许从理论上讲并不能保证,但实际上,使用函数调用的事实实际上是内存障碍.编译器不会对指令global.data = data进行重新排序,因为它不知道是否有人在函数调用中使用它,并且x86架构将确保在线程B从管道读取命令时其他CPU将看到此全局数据.世界上需要担心的问题.我们无需在虚假的理论问题上花费更多的精力.

"Quiet!", he hushed me promptly, "Maybe theoretically, it's not guaranteed, but in practice, the fact you used a function call is effectively a memory barrier. The compiler will not reorder the instruction global.data = data, since it can't know if anyone using it in the function call, and the x86 architecture will ensure that the other CPUs will see this piece of global data by the time thread B reads the command from the pipe. Rest assured, we have ample real world problems to worry about. We don't need to invest extra effort in bogus theoretical problems.

放心,我的孩子,随着时间的流逝,您会明白将真正的问题与我需要获得博士学位的非问题区分开来."

"Rest assured my boy, in time you'll understand to separate the real problem from the I-need-to-get-a-PhD non-problems."

他说得对吗?在实践中,这真的不是问题吗?(例如x86,x64和ARM)?

Is he correct? Is that really a non-issue in practice (say x86, x64 and ARM)?

这与我学到的一切都相违背,但他确实留着长胡子,看上去很聪明!

It's against everything I learned, but he does have a long beard and a really smart looks!

如果您能给我看一段代码证明他做错了,那就加分!

Extra points if you can show me a piece of code proving him wrong!

推荐答案

内存障碍不只是为了防止指令重新排序.即使指令没有重新排序,它仍然可能导致缓存一致性问题.至于重新排序-这取决于您的编译器和设置. ICC在重新排序方面特别具有攻击性.带有整个程序优化的MSVC也可以.

Memory barriers aren't just to prevent instruction reordering. Even if instructions aren't reordered it can still cause problems with cache coherence. As for the reordering - it depends on your compiler and settings. ICC is particularly agressive with reordering. MSVC w/ whole program optimization can be, too.

如果共享数据变量声明为volatile,则即使不在规范中,大多数编译器仍会围绕该变量的读取和写入生成一个内存变量,并防止重新排序. 这不是使用volatile的正确方法,也不是它的初衷.

If your shared data variable is declared as volatile, even though it's not in the spec most compilers will generate a memory variable around reads and writes from the variable and prevent reordering. This is not the correct way of using volatile, nor what it was meant for.

(如果我还有剩余票数,我将为您的叙述+1的问题.)

(If I had any votes left, I'd +1 your question for the narration.)

这篇关于函数调用是否是现代平台的有效内存屏障?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆