我想检查 gcc 和 icc 的各种优化选项的行为。采用了 Peterson 的 2 Thread mutex 算法。如果 lock 方法中 line a 和 line b(在注释中)的执行顺序被交换,则该算法可能会失败。使用带有 -O0 标志的 icc 或 gcc 进行编译会产生正确的结果。使用带有 -O3 标志的 icc 进行编译会产生不正确的结果。使用带有 -O3 标志的 gcc 进行编译不会产生任何结果。程序挂起。所以我的猜测是 gcc 和 icc 都使用 -O3 标志优化了锁定方法,并假设 a 行和 b 行之间没有依赖关系。因此,两者都产生了错误的结果。编译器很难找到这种依赖关系,所以有没有办法(如 ivdep 这样的编译指示)告诉编译器特定代码块中的依赖关系,这样我们仍然可以对代码的其他部分使用 -O3 标志
锁定方法:
void lock(int me)
{
int other;
other = 1-me;
flag[me] = 1; //Line a
victim = me; //Line b
while(flag[other]==1 && victim == me)
{
}
}
如果交换行 a 和行 b 的执行顺序,则违反 MUTEX 的示例:
T0 0 sets victim=0
T1 1 sets victim=1
T2 1 sets flag[1]=1
T3 1 checks flag[0]. flag[0] not yet set.
T4 1 enters CS
T5 0 sets flag[0]=1 and checks flag[1]. It is set but victim=1.
T6 0 also enters cs
完整代码:
#include<stdio.h>
#include<pthread.h>
#include<stdlib.h>
#include<time.h>
#include<stdint.h>
int flag[2];
int victim;
int sharedCounter=0;
void lock(int me)
{
int other;
other = 1-me;
flag[me] = 1;
victim = me;
while(flag[other]==1 && victim == me)
{
}
}
void unlock(int me)
{
flag[me]=0;
}
void *peterson(void *ptr)
{
int tId,i;
tId = (int ) (intptr_t) ptr;
for(i=0;i<200;i++)
{
lock(tId);
sharedCounter++;
printf("%d\t",sharedCounter);
sleep(1/10);
unlock(tId);
}
}
main()
{
int i;
for(i=0;i<2;i++)
{
flag[i]= 0;
}
pthread_t t[2];
for(i=0;i<2;i++)
{
pthread_create(&t[i],NULL,peterson,(void *) (intptr_t) i);
}
for(i=0;i<2;i++)
{
pthread_join(t[i],NULL);
}
printf("shared Counter:%d\n",sharedCounter);
exit(0);
}