【发布时间】:2016-02-24 06:29:34
【问题描述】:
我写了一个多线程程序来演示英特尔处理器的乱序效果。该程序附在本文末尾。 预期的结果应该是当 x 被 handler1 打印为 42 或 0 时。但是,实际结果始终为 42,这意味着不会发生乱序效应。
我用命令“gcc -pthread -O0 out-of-order-test.c”编译了程序 我在 Intel IvyBridge 处理器 Intel(R) Xeon(R) CPU E5-1650 v2 上的 Ubuntu 12.04 LTS(Linux 内核 3.8.0-29-generic)上运行编译程序。
有谁知道我应该怎么做才能看到乱序效果?
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
int f = 0, x = 0;
void* handler1(void *data)
{
while (f == 0);
// Memory fence required here
printf("%d\n", x);
}
void* handler2(void *data)
{
x = 42;
// Memory fence required here
f = 1;
}
int main(int argc, char argv[])
{
pthread_t tid1, tid2;
pthread_create(&tid1, NULL, handler1, NULL);
pthread_create(&tid2, NULL, handler2, NULL);
sleep(1);
return 0;
}
【问题讨论】:
-
这不是乱序,而是竞争条件。 (顺便说一句,x86 是一种有序加载/存储架构。)。
-
@Olaf,感谢您的评论。但是,根据stackoverflow.com/questions/7346893/…,x86 至少存在存储后加载问题。如果它对一个核心有数据依赖,我知道硬件会保持秩序。否则,乱序机制可能会在前一条指令之前执行下一条指令。
-
这里的乱序与指令执行无关。几乎不可能像(几乎)所有高端架构这样的多问题架构。这是关于加载/存储。但是你不会在这里利用你的 coe 来利用任何东西。并且可能不会使用任何 C 代码 - 至少不可靠。后者仅仅是因为您需要一个特定的指令序列,而在使用编译器时您将无法控制它。所以,潜入汇编程序并尝试。祝你好运。
-
您正在寻找preshing.com/20120515/memory-reordering-caught-in-the-act。 Jeff Preshing 的代码将演示 x86 上的 StoreLoad 重新排序(x86 上唯一可能的类型)。您永远不会在 x86 上看到 StoreStore 重新排序,因为它是强排序的。每个商店都有发布语义,每个加载都有获取语义。阅读 Preshing 博客上的其他帖子,了解这意味着什么。
-
在弱排序架构(如 ARM 或 PPC)上,您的代码可以观察 f=1 而没有 x=42,但您应该循环测试。只测试一次是极不可能找到任何东西的。在第二个线程启动之前,这两个商店可能都是全局可见的。 (无论如何,线程启动可能会在某个时候运行内存屏障指令!)
标签: c x86 synchronization memory-barriers barrier