@toc
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
find_package(OpenMP REQUIRED)
# Set Flags
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}")
# Header Path
include_directories(
${OpenMP_CXX_INCLUDE_DIRS}
)
# Link
target_link_libraries(target ${OpenMP_CXX_LIBRARIES})
openmp 代码段的起始符号
#pragma omp directive-name [clause[ [,] clause]...] new-line
directive-name
只能有一个;directive-name
选择:
#pragma omp parallel [clause[ [, ]clause] ...] new-line
structured-block
structured-block 中的代码会被并行执行;
但是并不代表 block 中的代码会被执行 N 次。针对 for loop 会被执行循环次数;针对 sections 只会执行一次。
#pragma omp for [clause[[,] clause] ... ] new-line
for-loop
for
属于 Work-sharing Constructs,本身并不会启动新的线程,只是将后续的代码分配到不同的线程;因此需要在 parallel
环境下使用。
for-loop 需要采用最普遍的写法 — for(int i = 0; i < 100; i++)
for 循环的末尾默认有一个 barrier (保证所有线程同时结束并入主线程),除非 clause 包含 nowait
clause 包含前两者的 clause,除了 nowait
#pragma omp parallel for [clause[[,] clause] ...] new-line
for-loop
section 之间是并行的。但是 sections 后的代码块只执行一次
#pragma omp parallel sections
{
[#pragma omp section new-line
structured-block]
[#pragma omp section new-line
structured-block]
...
}
single 后的代码块只被分配到一个线程(不一定是主线程),只执行一次。
master 后的代码块被分配到主线程。( single 特殊形式)
critical 后的代码块同一时间只有一个在执行。
atomic 后的代码块中访问的内存同一时间只暴露给一个线程。
部分编译器会把 atomic 当作 critical 处理,但是两者是有细微差别的。在进行原子操作时,atomic 的优化会比 critical 更好。
barrier & flush
barrier 同步所有线程;
flush:同步数据:CPU 将寄存器中的值写回内存,保证数据一致。
#pragma omp flush [(variable-list)] new-line
variable-list 为空,则等同于 barrier;
ordered 必须和 for 使用;ordered 后的代码块会按照 for 循环中的顺序执行。
同时 for 后的 clause 中需要有 ordered
部分 directive 允许用户通过 clause
更改后续代码块中变量的属性。这些改变仅在后续代码块中生效。当一个变量在 Construct 构建时是可见的,如果它既没有在 shared
也没有在 threadprivate
中出现,那么则是 shared
。动态申请的(堆中的)内存是 shared
(但是指针变量不一定是)。代码块中定义的变量是 private
。
shared
clause
private
clause:
每个线程都会调用默认构造函数构造一个相同类的实例。
copyin
clause:会将主线程中的对象复制到线程的私有变量中。