一、reduction子句
reduction子句可以對一個或者多個參數指定一個操作符,然後每一個線程都會創建這個參數的私有拷貝,在並行區域結束後,迭代運行指定的運算符,並更新原參數的值。
私有拷貝變量的初始值依賴於redtution的運算類型。
具體用法如下
reduction(operator:list)
#include <stdio.h>
#include <omp.h>
int main(int argc, char* argv[])
{
int i, sum = 10;
#pragma omp parallel for reduction(+: sum)
for (i = 0; i < 10; i++)
{
sum += i;
printf("%d\n", sum);
}
printf("sum = %ld\n", sum);
return 0;
}
二、copyin子句
copyin子句可以將主線程中變量的值拷貝到各個線程的私有變量中,讓各個線程可以訪問主線程中的變量。
copyin的參數必須要被聲明稱threadprivate,對於類的話則並且帶有明確的拷貝賦值操作符。
int g = 0;
#pragma omp threadprivate(g)
int main(int argc, char* argv[])
{
int i;
#pragma omp parallel for
for (i = 0; i < 4; i++)
{
g = omp_get_thread_num();
printf("thread %d, g = %d\n", omp_get_thread_num(), g);
}
printf("global g: %d\n", g);
#pragma omp parallel for copyin(g)
for (i = 0; i < 4; i++)
printf("thread %d, g = %d\n", omp_get_thread_num(), g);
return 0;
}
===== OUTPUT =====
thread 1, g = 1
thread 0, g = 0
thread 3, g = 3
thread 2, g = 2
global g: 0
thread 0, g = 0
thread 2, g = 0
thread 3, g = 0
thread 1, g = 0
三、schedule子句
OpenMP中的調度主要是指如何將任務分配給各個線程。主要有static和dynamic兩種。
1. static方式
在不指定調度方式的情形下,默認採用static方式。static方式是這樣的,假設有n次循環迭代,t個線程,那麼每個線程大約分到n/t次迭代。這種調度方式會將循環迭代均勻的分佈給各個線程,各個線程迭代次數可能相差1次。示例見下
int i;
#pragma omp parallel for schedule(static)
for (i = 0; i < 10; i++)
{
printf("i = %d, thread %d\n", i, omp_get_thread_num());
}
在靜態調度的時候,我們可以通過指定size參數來分配一個線程的最小迭代次數。換句話說,我們通過size參數可以指定一個線程的最小並行任務數。
int i;
#pragma omp parallel for schedule(static, 3)
for (i = 0; i < 4; i++)
{
printf("i = %d, thread %d\n", i, omp_get_thread_num());
}
===== OUTPUT =====
i = 3, thread 1
i = 0, thread 0
i = 1, thread 0
i = 2, thread 0
2. dynamic方式
動態分配是將迭代動態分配到各個線程,依賴於運行你狀態來確定,所以我們無法像靜態調度一樣事先預計進程的分配。哪一個線程先啓動,哪一個線程迭代多久,這些都取決於系統的資源和線程的調度。
int i;
#pragma omp parallel for schedule(dynamic)
for (i = 0; i < 10; i++)
{
printf("i = %d, thread %d\n", i, omp_get_thread_num());
}