OpenMP 简单的规约

时间:2024-05-23 16:04:26

▶ 简单的计算和规约

● 第一种方法,将全局和的指针传入工作函数中进行加和,使用 critical 来控制临界区的访问

 #include <stdio.h>
#include <stdlib.h>
#include <omp.h> const int thread = ; void work(int* globalSum)
{
#pragma omp critical // 使用 critical 来控制临界区的访问
*globalSum += omp_get_thread_num();
return;
} int main(int argc, char* argv[])
{
int threadReal, globalSum;
if (argc > && *argv[] > ''&& *argv[] < '')
threadReal = atoi(argv[]);
else
threadReal = thread;
globalSum = ; // 初始化全局和 #pragma omp parallel num_threads(threadReal)
work(&globalSum); // 将全局和的指针传给每个线程进行计算 printf("\nglobalSum = %d\n", globalSum);
getchar();
return ;
}

● 输出结果,下面几种方法的输出结果均相同,不再重复罗列

globalSum = 

● 第二种方法,使用局部变量,在主函数中进行加和

 #include <stdio.h>
#include <stdlib.h>
#include <omp.h> const int thread = ; int work()
{
return omp_get_thread_num();
} int main(int argc, char* argv[])
{
int threadReal, globalSum;
if (argc > && *argv[] > ''&& *argv[] < '')
threadReal = atoi(argv[]);
else
threadReal = thread;
globalSum = ; #pragma omp parallel num_threads(threadReal)
{
int localSum = work(); // 使用局部变量
#pragma omp critical
globalSum += localSum; // 将局部和加到全局和中
} printf("\nglobalSum = %d\n", globalSum);
getchar();
return ;
}

● 第三种方法,使用规约子句

 #include <stdio.h>
#include <stdlib.h>
#include <omp.h> const int thread = ; int work()
{
return omp_get_thread_num();
} int main(int argc, char* argv[])
{
int threadReal, globalSum;
if (argc > && *argv[] > ''&& *argv[] < '')
threadReal = atoi(argv[]);
else
threadReal = thread;
globalSum = ; #pragma omp parallel num_threads(threadReal) reduction(+ : globalSum)// 要求对 globalSum 使用加法规约
globalSum += work(); printf("\nglobalSum = %d\n", globalSum);
getchar();
return ;
}

● 第四种方法,使用 parallel for 循环

 #include <stdio.h>
#include <stdlib.h>
#include <omp.h> const int thread = ; int work()
{
return omp_get_thread_num();
} int main(int argc, char* argv[])
{
int i, threadReal, globalSum;
if (argc > && *argv[] > ''&& *argv[] < '')
threadReal = atoi(argv[]);
else
threadReal = thread;
globalSum = ; #pragma omp parallel for num_threads(threadReal) reduction(+:globalSum)// 联用了规约子句和 parallel for 循环
for (i = ; i < threadReal; i++)
globalSum += work(); printf("\nglobalSum = %d\n", globalSum);
getchar();
return ;
}

▶ 单独的 parallel for 用法

 #include <stdio.h>
#include <stdlib.h>
#include <omp.h> const int thread = ; int main(int argc, char* argv[])
{
int i, threadReal, a[thread];
if (argc > && *argv[] > ''&& *argv[] < '')
threadReal = atoi(argv[]);
else
threadReal = thread; #pragma omp parallel for num_threads(threadReal)
for (i = ; i < threadReal; i++)// 注意,把下面的 a[i] = i 写到括号里来会报错 “OpenMP“for”语句中的增量格式不正确”
a[i] = i; for (i = ; i < thread; i++)
printf("a[%2d] = %2d\n", i, a[i]);
getchar();
return ;
}

● 输出结果

a[ ] =
a[ ] =
a[ ] =
a[ ] =
a[ ] =
a[ ] =
a[ ] =
a[ ] =

▶ 使用私有变量估计 π 的值

 #include <stdio.h>
#include <stdlib.h>
#include <omp.h> const int thread = , count = ; int main0(int argc, char* argv[])// 一般方法,使用局部变量
{
int i, threadReal;
double sum;
if (argc > && *argv[] > ''&& *argv[] < '')
threadReal = atoi(argv[]);
else
threadReal = thread;
sum = 0.0; #pragma omp parallel for num_threads(threadReal) reduction(+ : sum)
for (i = ; i < count; i++)
{
double sign = (i % ? -1.0 : 1.0);
sum += sign / ( * i + );
} printf("π = %.10f\n", sum * );
getchar();
return ;
} int main1(int argc, char* argv[])// 将已经声明了的 sign 作为私有变量
{
int i, threadReal;
double sign, sum;
if (argc > && *argv[] > ''&& *argv[] < '')
threadReal = atoi(argv[]);
else
threadReal = thread;
sum = 0.0; #pragma omp parallel for num_threads(threadReal) reduction(+ : sum) private(sign)
for (i = ; i < count; i++)
{
sign = (i % ? -1.0 : 1.0);
sum += sign / ( * i + );
} printf("π = %.10f\n", sum * );
getchar();
return ;
} int main2(int argc, char* argv[])// 使用 default(none) 子句,然后明确规定每个变量的作用域
{
int i, threadReal;
double sign, sum;
if (argc > && *argv[] > ''&& *argv[] < '')
threadReal = atoi(argv[]);
else
threadReal = thread;
sum = 0.0; #pragma omp parallel for num_threads(threadReal) reduction(+ : sum) default(none) private(i, sign) shared(count)// 多个变量用逗号隔开
for (i = ; i < count; i++)
{
sign = (i % ? -1.0 : 1.0);
sum += sign / ( * i + );
} printf("π = %.10f\n", sum * );
getchar();
return ;
}

● 输出结果

π = 3.1415826536