【问题标题】:OpenMP shared variable seems to be privateOpenMP 共享变量似乎是私有的
【发布时间】:2015-06-13 11:33:17
【问题描述】:

我不明白为什么在这段代码中只有线程 0 有 n = 1 而其他线程有 n = 0 且 shared n

int main()
{
    int n, tid;

    #pragma omp parallel shared(n) private(tid)
    {
            tid = omp_get_thread_num();
            n = 0;

            if (tid == 0)
            {
                    n++;
            }

            printf("I'am %d, this is my n: %d\n", tid, n);
    }

    return 0;

}

输出:

I'am 5, this is my n: 0
I'am 7, this is my n: 0
I'am 0, this is my n: 1
I'am 2, this is my n: 0
I'am 4, this is my n: 0
I'am 3, this is my n: 0
I'am 6, this is my n: 0
I'am 1, this is my n: 0

我是 OMP 库的新手。我在一个有 8 个节点的集群上通过 ssh 工作,这可能是问题吗?

谢谢。

【问题讨论】:

    标签: c parallel-processing openmp


    【解决方案1】:

    您实际上是通过每个线程将n 重置为零。只有带有tid==0 的线程会在打印之前增加n。即使在这里,您也可能会遇到程序打印

    我是 0,这是我的 n: 0

    而不是预期的

    我是 0,这是我的 n:1

    因为你制作了一个所谓的race condition

    如果您打算仅在运行时开始时将 n 初始化为零,则需要更早地初始化 n,例如在开始并行部分之前:

    n = 0;
    
    #pragma omp parallel shared(n) private(tid)
    {
            tid = omp_get_thread_num();
    
            if (tid == 0)
            {
                    n++;
            }
    
            printf("I'am %d, this is my n: %d\n", tid, n);
    }
    

    但是请注意,打印列表中 n 的状态将再次变得有些随机,因为您永远无法确定线程 0 何时将 n 的值增加到等于 1。

    【讨论】:

    • @Maghio:不用担心,竞争条件是并行编程中最常见的问题之一,有时很难追踪。很高兴我能帮上忙。请接受我/我的回答以表明已找到解决方案。
    • 我将在打印前使用“#pragma omp barrier”!
    • @Maghio:请注意,您还需要按照指示重新定位 n 的初始化。否则即使使用屏障,另一个线程也可能将值重置为零。
    • @fuesike:那是不可能的。在执行omp_set_num_threads() 期间,您甚至还没有拥有 任何线程(因为它在parallel 块之外),那么您怎么可能给它分配任何东西呢?
    • @Maghio:未指定如何分配数字。您只知道主线程将具有 0,而其他线程将具有 1 和线程数减 1 之间的任何数字。即使您知道某个 OpenMP 实现如何分配数字,您也不应该依赖它,因为另一个实现可以做不同的事情。
    【解决方案2】:

    最后这应该是让每个线程打印“n=1”的代码:

    int main()
    {
        int n=0, t;
    
        #pragma omp parallel shared(n) private(t)
        {
                t = omp_get_thread_num();
    
                if (t == 0)
                {
                        n++;
                }
    
                #pragma omp barrier
                printf("Sono %d e ho n = %d\n", t, n);
        }
    
        return 0;
    

    }

    感谢 fuesika。

    【讨论】:

    • 如果线程 2 最先到达“if (t==0)”,那又会怎样呢?这个小代码是关于线程竞争以及事情如何出错的主要例子。在上面的示例中,由于(一个或多个)CORE-s 中的 NUMA 和其他意外条件,没有人可以保证首先执行线程 0。 PS:这个答案应该被保护为错误答案。
    猜你喜欢
    • 2017-05-15
    • 1970-01-01
    • 1970-01-01
    • 2012-04-14
    • 2011-09-15
    • 1970-01-01
    • 1970-01-01
    • 2018-01-30
    • 1970-01-01
    相关资源
    最近更新 更多