OpenMP 赵学长培训笔记
2024年三月OpenMP培训笔记
一、最简单的一个程序
1 2 3 4 5 6 7 8 9
| #include <stdio.h> int main() { #pragma omp parallel \\通知以下代码是OpenMp的指令和结构化块,也称为构造 { printf("Hello world \n"); } return 0; }
|
进行编译(linux):
1 2 3 4 5
| $ gcc -fopenmp a.c $ ./a.out or $ gcc -fopenmp a.c -o a \\编译a.c程序 $ ./a
|
-fopenmp
指令告诉编译器用OpenMp创造一个多线程程序
1 2
| $export OMP_NUM_THREADS=4 \\设置线程数为4 $./c
|
修改线程数后无需再次编译,直接运行即可
运行结果:
二、OpenMP API与两个重要函数
使用OpenMP相关函数时添加头文件:
获取线程数的接口
1 2
| omp_get_thread_num() \\获得当前线程的线程数id omp_get_num_threads() \\获得总线程数
|
Example:
1 2 3 4 5 6 7 8 9 10 11 12
| #include <stdio.h> #include <omp.h>
int main() { #pragma omp parallel { int tid = omp_get_thread_num(); int ths = omp_get_num_threads(); printf("tid=%d ths=%d \n",tid,ths); } return 0; }
|
由此图同时可知,线程的运行是无序并行的
三、OpenMP 基础语法
3.1 并行处理循环语句
1 2 3 4
| #prama omp parrallel for for(int i=1=0;i<n;i++){ ... }
|
将n次循环分给可用的线程进行处理
1 2 3 4 5 6 7 8 9 10 11 12 13
| #include <stdio.h> #include<omp.h> int main() { int ths = omp_get_num_threads(); #pragma omp parallel for for(int i=0;i<16;i++) { int tid=omp_get_thread_num(); printf("Thread %d of threads %d is handling %dth loop\n",tid,ths,i); } return 0; }
|
注意,此处#pragma omp parallel for
外层无需再套一层pragma omp parallel
否则只能利用一个线程。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| #include <stdio.h> #include<omp.h> int main() { #pragma omp parallel { int ths = omp_get_num_threads(); #pragma omp parallel for for(int i=0;i<16;i++) { int tid=omp_get_thread_num(); printf("Thread %d of threads %d is handling %dth loop\n",tid,ths,i); }
} return 0; }
|
原因:parrallel
为构造一个并行域 ,内层的#pragma omp parallel for
相当于利用一个线程再构造了一个并行域运行,
在此处线程数为4时实际会运行 4x16
次printf()