Peterson 算法对于各种优化标志的行为

问题描述 投票:0回答:1

我想检查 gcc 和 icc 的行为以获取各种优化选项。 采用 Peterson 的 2 线程互斥算法。如果lock方法中a行和b行(在注释中)的执行顺序互换,则该算法可能会失败。 使用带有 -O0 标志的 icc 或 gcc 编译会产生正确的结果。 使用带有 -O3 标志的 icc 编译会产生不正确的结果。 使用带有 -O3 标志的 gcc 编译不会产生任何结果。程序挂起。 所以我的猜测是,使用 -O3 标志,gcc 和 icc 都优化了锁定方法,并假设 a 行和 b 行之间没有依赖关系。因此两者都产生了错误的结果。 这种依赖关系对于编译器来说很难找到,那么有没有办法(像 ivdep 这样的 pragmas)告诉编译器特定代码块中的依赖关系,以便我们仍然可以对代码的其他部分使用 -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);
}
c multithreading algorithm parallel-processing compiler-optimization
1个回答
2
投票

将变量声明为“易失性”将仅防止对这些变量的读取或写入进行重新排序。

© www.soinside.com 2019 - 2024. All rights reserved.