Openmp 共享变量子句

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

如果我在 main 内部和 #pragma omp parallel 之上声明一个变量 int n=5 ,那么它是由并行区域内的所有线程共享的,所以我的问题是这个 n 变量存储在哪里以及线程如何访问它,其机制是什么后面?

n 是否存储在堆上?或者在主堆栈中或在其他区域中。?请解释一下

openmp shared clause
1个回答
0
投票

正如 @Jérôme-Richard 所说,OpenMP(r) 标准并未指定这一点。然而,至少 LLVM(所以现在大多数供应商编译器)和 GCC 在堆栈上分配一个局部变量,即使它后来被共享。

您可以在编译器资源管理器示例之类的代码中看到这一点,它计算由未修饰的

omp parallel
创建的线程数。 (当然,有很多更简单的方法可以做到这一点,但它是一个相对较小、易于理解的示例)。

    int availableThreads()
    {
        int s = 0;  
    
        #pragma omp parallel shared(s)
        {
            #pragma omp atomic
            s += 1;
        }
        return s;
    }

考虑(带注释的)LLVM 生成的代码:-

availableThreads:                       # @availableThreads
        push    rax
        mov     dword ptr [rsp + 4], 0 # Allocate s on the stack and zero it
        lea     rdi, [rip + .L__unnamed_1]
        lea     rdx, [rip + availableThreads.omp_outlined]
        lea     rcx, [rsp + 4] # Pass the address of s in rcx
        mov     esi, 1
        xor     eax, eax
        call    __kmpc_fork_call@PLT
        mov     eax, dword ptr [rsp + 4]
        pop     rcx
        ret

availableThreads.omp_outlined:          # @availableThreads.omp_outlined
        lock            inc     dword ptr [rdx]
        ret

.L__unnamed_2:
        .asciz  ";/app/example.c;availableThreads;6;5;;"

.L__unnamed_1:
        .long   0                               # 0x0
        .long   2                               # 0x2
        .long   0                               # 0x0
        .long   38                              # 0x26
        .quad   .L__unnamed_2

我们可以看到

s
在外部函数中被分配和归零,并且其地址被传递到 OpenMP 运行时 fork 函数中。在概述的并行体 (
availableThreads.omp_outlined
) 中,我们可以看到运行时作为唯一参数传入的值,并且指针的目标以原子方式递增。

GCC 代码类似(如果您想查看它,请使用 Compiler Explorer 示例,或者看看其他架构上会发生什么)。

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