Mik*_*ike 2 c x86 synchronization memory-barriers barrier
我写了一个多线程程序来演示英特尔处理器的乱序效果.该计划附在本文末尾.预期的结果应该是当handler1将x打印为42或0时.但是,实际结果总是为42,这意味着不会发生乱序效应.
我使用命令"gcc -pthread -O0 out-of-order-test.c"编译了程序.我在Intel IvyBridge处理器Intel(R)上运行Ubuntu 12.04 LTS(Linux内核3.8.0-29-通用)上的编译程序)Xeon(R)CPU E5-1650 v2.
有谁知道我应该怎么做才能看到乱序效果?
#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;
}
Run Code Online (Sandbox Code Playgroud)
您正在将竞争条件与无序执行范例混合在一起.不幸的是,我很确定你不能"暴露"乱序执行,因为它是以明确的方式设计和实现的,以便保护你(正在运行的程序及其数据)免受其影响.
更具体地说:乱序执行完全发生在CPU"内部".无序指令的结果不会直接发布到寄存器文件中,而是排队等候以保留订单.因此,即使指令本身不按顺序执行(基于主要确保这些指令可以彼此独立运行的各种规则),它们的结果总是被重新排序为正确的顺序,如外部观察者所期望的那样. .
你的程序所做的是:它试图(非常粗略地)来模拟中,你希望看到的分配竞争条件f,以提前完成的x ,并在同一时间,你希望有一个上下文切换发生正是在那一刻和您假设新线程将在与另一个相同的CPU核心上进行调度.但是,正如我上面所解释的那样 - 即使你足够幸运地达到所有列出的条件(在f分配之后但在x分配之前安排第二个线程并且在同一个CPU核心上安排新线程) - 这是在本身是一个非常低概率的事件 - 即使这样你真正暴露的是一个潜在的竞争条件,但不是无序执行.
很抱歉让您失望,但您的程序无法帮助您观察无序执行效果.至少没有足够高的概率才能实用.
您可以在这里阅读更多关于无序执行的内容:http: //courses.cs.washington.edu/courses/csep548/06au/lectures/introOOO.pdf
更新 我考虑过一些想法,我认为你可以在飞行中修改指令,希望暴露出无序执行.但即使这样,我担心这种方法会失败,因为新的"更新"指令将无法正确反映在CPU的管道中.我的意思是:CPU很可能已经获取并解析了您要修改的指令,因此将执行的内容将不再与内存字的内容(即使是CPU的L1缓存中的内容)相匹配.但是这种技术,假设它可以帮助你,需要在Assembly中直接进行一些高级编程,并且需要你的代码以最高权限级别(ring 0)运行.我建议在编写自修改代码时要特别小心,因为它具有很大的副作用潜力.