[多线程/并行编程]配置 openmp/libgomp 库

C/C++第三方开源库的介绍和相关讨论
头像
523066680
Administrator
Administrator
帖子: 369
注册时间: 2016年07月19日 12:14
拥有现金: 锁定
储蓄: 锁定
Has thanked: 32 times
Been thanked: 36 times
联系:

[多线程/并行编程]配置 openmp/libgomp 库

帖子 #1 523066680 » 2016年10月22日 11:40

http://openmp.org的描述是:The OpenMP API specification for parallel programming

关于这个库的获取
  1. 安装TDM-GCC (4.x版本或以上)的时候,带有omp.h,但实际没有解压相关库文件,需要在安装时点开选项列表,选中openmp再安装
    图片

  2. tdm-gcc.tdragon.net/download Packages 下方的列表中下载 gcc-5.1.0-tdm64-1-openmp.zip
    或者从 Sourceforege - tdm-gcc 页面 中下载 gcc-5.1.0-tdm64-1-openmp.zip,里面已经包含32位和64位的静态库和动态库

源码在gcc源码包中(sourceforge):
TDM-GCC MinGW Compiler Sources / Vanilla Sources / gcc-5.1.0.tar.bz2
MinGW MinGW / Base / gcc / Version5 / gcc-5.3.0-2 / gcc-5.3.0-2-mingw32-src.tar.xz

示例代码
https://github.com/OpenMP/Examples


编译器支持
主流C/C++编译器,如gcc与visual C++,都内在支持OpenMP。一般都必须在程序中#include <omp.h>

Visual C++需要在IDE的编译选项->语言->支持OpenMP。这实际上使用了编译选项/openmp


优点和缺点

优点
可移植的多线程代码(在C/C++和其他语言中,人们通常为了获得多线程而调用特定于平台的原语)
简单,没必要向MPI中那样处理消息传递
增量并行,一次可以只在代码的一部分执行,对代码不需要显著的改变
统一的顺序执行和并行执行的代码,在顺序执行编译器上,OpenMP的执行按照注释进行对待;

缺点
存在引入难以调试的同步错误和竞争条件的风险
目前,只能在共享内存的多处理器平台高效运行
需要一个支持OpenMP的编译器
可扩展性是受到内存架构的限制
不支持比较和交换
在GPU上不能使用
多线程的可执行文件的启动需要更多的时间,可能比单线程的运行的慢,因此,使用多线程一定要有其他有优势的地方
很多情况下使用多线程不仅没有好处,还会带来一些额外消耗


gcc-5.1.0-tdm64-1-openmp.zip
(313.17 KiB) 下载 25 次
gcc-5.1.0-tdm64-1-openmp.zip
(313.17 KiB) 下载 25 次


omp.h
(4.25 KiB) 下载 8 次
omp.h
(4.25 KiB) 下载 8 次


分割线

头像
523066680
Administrator
Administrator
帖子: 369
注册时间: 2016年07月19日 12:14
拥有现金: 锁定
储蓄: 锁定
Has thanked: 32 times
Been thanked: 36 times
联系:

编译示例代码

帖子 #2 523066680 » 2016年10月22日 21:35

示例代码:

Code: [全选] [展开/收缩] [Download] (example.c)
  1. #include <stdio.h>
  2.  
  3. int main(int argc, char *argv[] )
  4. {
  5.     #pragma omp parallel
  6.     {
  7.         printf("TEST\n");
  8.     }
  9.     return 0;
  10. }


编译

使用 Nuwen.net 提供的离线MinGW环境

    这个程序直接 gcc example.c 就可以通过,运行输出一行 TEST,原因就是没有开启openmp开关。

    > gcc example.c -fopenmp
    gcc: error: libgomp.spec: No such file or directory

    将 gcc-5.1.0-tdm64-1-openmp.zip 中的 libgomp.a, libgomp.spec 放在当前目录

    > gcc example.c -fopenmp
    c:/mingw/bin/../lib/gcc/x86_64-w64-mingw32/6.1.0/../../../../x86_64-w64-mingw32/
    bin/ld.exe: cannot find -lgomp
    c:/mingw/bin/../lib/gcc/x86_64-w64-mingw32/6.1.0/../../../../x86_64-w64-mingw32/
    bin/ld.exe: cannot find -lpthread

    添加编译参数 -L.
    但是 libpthread.a 就只有在tdm-gcc-64 中能找到,也复制到当前目录
    > gcc example.c -fopenmp -L.

    > a
    TEST
    TEST
    TEST
    TEST
    TEST
    TEST
    TEST
    TEST


    直接 gcc example.c -L. -I. -lgomp 虽然编译通过,但也是达不到多线程的效果的,必须开启 -fopenmp

使用tdm-gcc-64 or tdm-gcc-32

    PATH=D:\tdm-gcc-32\bin

    静态链接
    将 libgomp.a 放在当前目录下(注意辨别64位/32位)
    > gcc example.c -fopenmp -L.
    编译后即可运行

    动态链接
    > gcc example.c -fopenmp
    将 libgomp_64-1.dll 或者 libgomp-1.dll 放在运行环境中方可运行。

头像
523066680
Administrator
Administrator
帖子: 369
注册时间: 2016年07月19日 12:14
拥有现金: 锁定
储蓄: 锁定
Has thanked: 32 times
Been thanked: 36 times
联系:

Re: [多线程/并行编程]配置 openmp/libgomp 库

帖子 #3 523066680 » 2016年10月26日 08:50

第二个示例(当用到omp相关的函数时,就需要 #include <omp.h> 了 )

Code: [全选] [展开/收缩] [Download] (Untitled.c)
  1. #include <stdio.h>
  2. #include <omp.h>
  3.  
  4. int main(int argc, char *argv[] )
  5. {
  6.     #pragma omp parallel num_threads(6)
  7.     {
  8.         printf("Thread %d\n", omp_get_thread_num() );
  9.     }
  10.     return 0;
  11. }


openmp>set path=D:\TDM-GCC-32\BIN

openmp>gcc get_thread_num.c -o get_thread_num -fopenmp -L.

openmp>get_thread_num

Thread 2
Thread 4
Thread 1
Thread 0
Thread 3
Thread 5


相关教程和文章,暂时贴这里了
[ibm.com]通过 GCC 学习 OpenMP 框架

wikipedia

GCC在线手册 - libgomp

头像
523066680
Administrator
Administrator
帖子: 369
注册时间: 2016年07月19日 12:14
拥有现金: 锁定
储蓄: 锁定
Has thanked: 32 times
Been thanked: 36 times
联系:

Re: [多线程/并行编程]配置 openmp/libgomp 库

帖子 #4 523066680 » 2016年10月28日 16:08

omp_get_max_threads() 获取最大线程数

一般默认是和CPU核数相同,比如8核,那么调用这个函数返回8。4核返回4
但是这个限制也可以自己手动修改,比如
omp_set_num_threads( 16 );
但是我想,如果是大量运算的话,把线程改的特别多也没有意义,因为硬件限制在那里。


为 for 提供多线程处理

假设有一个函数,里面的操作相对耗时(比如和网络有关),需要2秒( 暂时用 usleep 表示 )
就可以用openmp 实现并行,但是执行顺序不是线性的

Code: [全选] [展开/收缩] [Download] (Untitled.c)
  1. #include <stdio.h>
  2. #include <omp.h>
  3. #include <unistd.h>
  4.  
  5. void func(long i)
  6. {
  7.     usleep(999999);
  8.     usleep(999999);
  9.     printf("%d ", i);
  10. }
  11.  
  12. int main(int argc, char *argv[] )
  13. {
  14.     long i;
  15.     long N = 32;
  16.  
  17.     omp_set_num_threads( 8 );               //设置线程数
  18.     #pragma omp parallel for
  19.     for (i=0; i<N; ++i)
  20.     {
  21.         func(i);
  22.     }
  23.     return 0;
  24. }


输出结果
4 12 16 8 24 0 20 28 13 29 5 21 1 9 25 17 2 10 14 30 18 6 26 22 3 11 19 27 15 31
7 23


回到 “扩展库”

在线用户

用户浏览此论坛: 没有注册用户 和 1 访客