具有函数作用域静态变量初始化的 threadprivate
threadprivate with initialization of function-scope static variables
我正在测试 threadprivate
子句在 openMP 中的工作方式。我设置了以下简单的测试用例
#include <iostream>
#include <omp.h>
void func(){
static int some_id = omp_get_thread_num();
#pragma omp threadprivate(some_id)
#pragma omp critical
{
std::cout << "id:" << some_id << std::endl;
std::cout << "in thread " << omp_get_thread_num() << std::endl;
}
}
int main() {
omp_set_num_threads(4);
#pragma omp parallel
func();
}
我用 gcc7.2 和 运行 编译了这段代码,我得到了
id:1
in thread 1
id:0
in thread 0
id:0
in thread 3
id:0
in thread 2
我知道 C++ 标准(至少从 C++03 标准开始)保证静态变量由一个且只有一个线程初始化,所有其他线程都被阻塞,直到初始化完成。话虽如此,我希望所有线程中 id
的本地副本都具有相同的值(负责初始化的线程的 ID)。为什么线程#1 中的 id
与其他线程中的不同?显然我的 threadprivate
心智模型是有缺陷的。你能解释一下这是怎么回事吗?
我认为这是实现中的错误。 OpenMP API 规范要求 some_id
变量由每个线程初始化:
Each copy of a block-scope threadprivate variable that has a dynamic
initializer is initialized the first time its thread encounters its
definition; if its thread does not encounter its definition, its
initialization is unspecified.
(见https://www.openmp.org/spec-html/5.1/openmpsu114.html#x149-1630002.21.2)
我机器上的 GCC 9.3.0 具有相同的行为:
$ g++ --version
g++ (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0
Copyright (C) 2019 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
$ g++ -O0 -g -fopenmp -o tp tp.cc
$ ./tp
id:0
in thread 0
id:0
in thread 3
id:0
in thread 1
id:0
in thread 2
虽然 clang 12 做了正确的事情:
$ clang --version
clang version 12.0.0 (/net/home/micha/projects/llvm/llvm-project/clang d28af7c654d8db0b68c175db5ce212d74fb5e9bc)
Target: x86_64-unknown-linux-gnu
Thread model: posix
InstalledDir: /net/software/x86_64/clang/12.0.0/bin
$ clang++ -g -O0 -fopenmp -o tp ./tp.cc
$ ./tp
id:2
in thread 2
id:0
in thread 0
id:3
in thread 3
id:1
in thread 1
我正在测试 threadprivate
子句在 openMP 中的工作方式。我设置了以下简单的测试用例
#include <iostream>
#include <omp.h>
void func(){
static int some_id = omp_get_thread_num();
#pragma omp threadprivate(some_id)
#pragma omp critical
{
std::cout << "id:" << some_id << std::endl;
std::cout << "in thread " << omp_get_thread_num() << std::endl;
}
}
int main() {
omp_set_num_threads(4);
#pragma omp parallel
func();
}
我用 gcc7.2 和 运行 编译了这段代码,我得到了
id:1
in thread 1
id:0
in thread 0
id:0
in thread 3
id:0
in thread 2
我知道 C++ 标准(至少从 C++03 标准开始)保证静态变量由一个且只有一个线程初始化,所有其他线程都被阻塞,直到初始化完成。话虽如此,我希望所有线程中 id
的本地副本都具有相同的值(负责初始化的线程的 ID)。为什么线程#1 中的 id
与其他线程中的不同?显然我的 threadprivate
心智模型是有缺陷的。你能解释一下这是怎么回事吗?
我认为这是实现中的错误。 OpenMP API 规范要求 some_id
变量由每个线程初始化:
Each copy of a block-scope threadprivate variable that has a dynamic initializer is initialized the first time its thread encounters its definition; if its thread does not encounter its definition, its initialization is unspecified.
(见https://www.openmp.org/spec-html/5.1/openmpsu114.html#x149-1630002.21.2)
我机器上的 GCC 9.3.0 具有相同的行为:
$ g++ --version
g++ (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0
Copyright (C) 2019 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
$ g++ -O0 -g -fopenmp -o tp tp.cc
$ ./tp
id:0
in thread 0
id:0
in thread 3
id:0
in thread 1
id:0
in thread 2
虽然 clang 12 做了正确的事情:
$ clang --version
clang version 12.0.0 (/net/home/micha/projects/llvm/llvm-project/clang d28af7c654d8db0b68c175db5ce212d74fb5e9bc)
Target: x86_64-unknown-linux-gnu
Thread model: posix
InstalledDir: /net/software/x86_64/clang/12.0.0/bin
$ clang++ -g -O0 -fopenmp -o tp ./tp.cc
$ ./tp
id:2
in thread 2
id:0
in thread 0
id:3
in thread 3
id:1
in thread 1