pthread vs openMP之我见

  前两天看了些并行计算的文章,了解了一些并行计算的方法和原理。然后发现多线程实现里面还有个openMP,这个以前从来没见过(火星了),之前只是知道pthread线程库和微软也实现了一套线程。又看了看openMP的一些教程才知道它是怎么回事。

  pthread全称应该是POSIX THREAD,顾名思义这个肯定是按照POSIX对线程的标准而设计的。目前我所知道的有两个版本:Linux Thread(较早)和NPTL(主流?)。pthread库是一套关于线程的API,提供“遵循”(各平台实现各异)POSIX标准的线程相关的功能。

  openMP不同于pthread的地方是,它是根植于编译器的(也要包含头文件omp.h),而不是在各系统平台是做文章。它貌似更偏向于将原来串行化的程序,通过加入一些适当的编译器指令(compiler directive)变成并行执行,从而提高代码运行的速率。如:

1 #include<omp.h>
2 #include<stdio.h>
3
4  #define ARRAY_SIZE 1000
5  #define CHUNK_SIZE 100
6
7  int main()
8 {
9 int array[ARRAY_SIZE];
10 int thread_num = ARRAY_SIZE/CHUNK_SIZE+1;
11 omp_set_num_threads(thread_num);
12
13 //init array
14   int i;
15 for(i=0;i<ARRAY_SIZE;i++)
16 {
17 array[i]=i;
18 }
19
20  #pragma omp parallel for schedule(guided,CHUNK_SIZE) private(i)
21 for(i=0;i<ARRAY_SIZE;i++)
22 {
23 int n = array[i];
24 int num_of_one=0;
25 if(n!=0)
26 {
27 num_of_one++;
28 while((n=n&(n-1))!=0)
29 {
30 num_of_one++;
31 }
32 }
33 array[i]=num_of_one;
34
35 }
36 for(i=0;i<ARRAY_SIZE;i++)
37 {
38 printf("%d ",array[i]);
39 }
40 printf("\n");
41 return 0;
42
43 }
44
45  

  上面一段代码是通过加了一条函数调用(11行)和一条编译器指令(20行),从而将原来的循环分给多个线程来做。(本程序是计算0~ArraySize-1的每个数中二进制包含1个数)。

  而对于一开始就打算用并行方法来实现的程序,用pthread应该是更方便和更清晰。

下面是分别用pthread和openMP实现的worker_and_consumer:

pthread版:

ContractedBlock.gifExpandedBlockStart.gif代码
1 #include<unistd.h>
2 #include<pthread.h>
3 #include<stdio.h>
4 #include<stdlib.h>
5
6  #define SIZE 100
7  #define THREAD_NUM_WORKER 15
8 #define THREAD_NUM_CONSUMER 10
9 #define SLEEP_WORKERS 2
10 #define SLEEP_CONSUMERS 1
11
12 int warehouse[SIZE];
13 int at =-1;
14 int is_end =0;
15 pthread_mutex_t space = PTHREAD_MUTEX_INITIALIZER;
16 pthread_mutex_t end = PTHREAD_MUTEX_INITIALIZER;
17
18 void* consumer_func(void*);
19 void* worker_func(void*);
20
21 int main()
22 {
23 pthread_t workers[THREAD_NUM_WORKER];
24 pthread_t consumers[THREAD_NUM_CONSUMER];
25 int i,j;
26 int n;
27 for(i=0;i<THREAD_NUM_WORKER;i++)
28 pthread_create(&workers[i],NULL,worker_func,NULL);
29 for(j=0;j<THREAD_NUM_CONSUMER;j++)
30 pthread_create(&consumers[j],NULL,consumer_func,NULL);
31 while(is_end==0)
32 {
33 scanf("%d",&n);
34 if(n==0)
35 {
36 pthread_mutex_lock(&end);
37 is_end=1;
38 pthread_mutex_unlock(&end);
39 }
40 }
41 for(i=0;i<THREAD_NUM_WORKER;i++)
42 pthread_join(workers[i],NULL);
43 for(j=0;j<THREAD_NUM_CONSUMER;j++)
44 pthread_join(consumers[j],NULL);
45 return 0;
46 }
47
48 void* worker_func(void* var)
49 {
50 while(1)
51 {
52 if(is_end)
53 break;
54 //保护at变量
55 pthread_mutex_lock(&space);
56 if(SIZE-at-1>0)
57 {
58 printf("Make %d by worker %lld ",warehouse[++at]=rand(),pthread_self());
59 printf("and at is %d\n",at);
60 }
61 pthread_mutex_unlock(&space);
62 sleep(SLEEP_WORKERS);
63 }
64 return NULL;
65 }
66
67
68 void* consumer_func(void* var)
69 {
70 while(1)
71 {
72 if(is_end)
73 break;
74 pthread_mutex_lock(&space);
75 if(at>=0)
76 {
77 printf("Got %d by consumer %lld\n",warehouse[at--],pthread_self());
78 printf("and at is %d\n",at);
79 }
80 pthread_mutex_unlock(&space);
81 sleep(SLEEP_CONSUMERS);
82 }
83 return NULL;
84 }
85
86
87
88

openMP版:

ContractedBlock.gifExpandedBlockStart.gif代码
1 #include<unistd.h>
2 #include<stdio.h>
3 #include<stdlib.h>
4 #include<omp.h>
5
6
7 #define SIZE 100
8 #define THREAD_NUM_WORKER 15
9 #define THREAD_NUM_CONSUMER 10
10 #define SLEEP_WORKERS 2
11 #define SLEEP_CONSUMERS 1
12
13 int warehouse[SIZE];
14 int at =-1;
15 int is_end =0;
16
17 void start_workers()
18 {
19 omp_set_num_threads(THREAD_NUM_WORKER);
20 #pragma omp parallel default(shared)
21 {
22 if(omp_get_thread_num()==0)
23 printf("worker num is %d\n",omp_get_num_threads());
24 while(1)
25 {
26 if(is_end)
27 break;
28 //保护at变量
29 #pragma omp critical(space)
30 {
31 if(SIZE-at-1>0)
32 {
33 printf("Make %d by worker %d ",warehouse[++at]=rand(),omp_get_thread_num());
34 printf("and at is %d\n",at);
35 }
36 }
37 sleep(SLEEP_WORKERS);
38 }
39 }
40 }
41
42
43 void start_consumers(void)
44 {
45 omp_set_num_threads(THREAD_NUM_CONSUMER);
46 #pragma omp parallel default(shared)
47 {
48 if(omp_get_thread_num()==0)
49 printf("consumer num is %d\n",omp_get_num_threads());
50 while(1)
51 {
52 if(is_end)
53 break;
54 #pragma omp critical(space)
55 {
56 if(at>=0)
57 {
58 printf("Got %d by consumer %d\n",warehouse[at--],omp_get_thread_num());
59 printf("and at is %d\n",at);
60 }
61 }
62 sleep(SLEEP_CONSUMERS);
63 }
64 }
65 }
66
67 int main()
68 {
69 omp_set_dynamic(0);
70 omp_set_nested(1);//这个不设置的话,就不能嵌套fork子线程咯
71 //先设置3个线程,每个线程完成一个section
72 omp_set_num_threads(3);
73 #pragma omp parallel sections
74 {
75 #pragma omp section
76 {
77 start_workers();
78 }
79 #pragma omp section
80 {
81 start_consumers();
82 }
83 #pragma omp section
84 {
85 int in;
86 scanf("%d",&in);
87 if(!in)
88 {
89 //保护is_end
90 #pragma omg critical(end)
91 is_end =1;
92 }
93 }
94 }
95 return 0;
96 }
97
98
99

  最后说一下,用openMP,编译时要加上选项-fopenmp,编译pthread时加上链接-lpthread。另外openMP有个缺点是若是代码中编译指令出错时,找错还是挺麻烦的,就像昨晚我把#pragma omp parallel写成了#pragma omg parallel,结果编译链接通过后却始终只有一个线程(主线程),找了好久...囧!

转载于:https://www.cnblogs.com/wwillforever/archive/2010/12/02/1894229.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/350033.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

线程池默认多少个线程_我需要多少个线程?

线程池默认多少个线程这取决于您的应用程序。 但是&#xff0c;对于那些希望对如何从生产站点购买的所有昂贵内核中挤出大量资金的人&#xff0c;请多多包涵&#xff0c;我将阐明围绕多线程 Java应用程序的奥秘。 内容针对最典型的Java EE应用程序进行了“优化”&#xff0c;该…

mysql error writing_MySQL:Error writing file (Errcode: 28)解决方法

问题描述&#xff1a;在执行创建表语句时提示&#xff1a;mysql> CREATE TABLE cash_request (id int(11) NOT NULL auto_increment,dev_id int(11) NOT NULL,bank_account_info varchar(255) NOT NULL,money int(11) NOT NULL,status tinyint(1) NOT NULL default 1,is_fan…

[暑假集训Day4T3]曲线

三分模板。 三分法求单峰函数最优值,之后每次取所有二次函数最优值即可 #pragma GCC optimize(3,"Ofast","inline") #include<iostream> #include<cstdio> #define N 100005 #define eps 1e-9 using namespace std; int read() {int x0,f1;cha…

模拟Spring Security上下文进行单元测试

今天&#xff0c;在为一种Java方法编写单元测试用例时&#xff0c;如下所示&#xff1a; public ApplicationUser getApplicationUser() {ApplicationUser applicationUser (ApplicationUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal();return…

mysql semi-synchronous_MySQL Semisynchronous Replication介绍

前言MySQL 5.5版本之前默认的复制是异步(Asynchronous )模式的, MySQL 5.5 以plugins的方式提供了Semisynchronous Replication 模式。在介绍 semi sync 之前,我们先了解&#xff1a;半同步 Asynchronous 和 同步 Synchronous 。异步复制模式主库将已经提交的事务event 写入bin…

Jquery屏蔽回车键

1 $(function(){2 3 $(“#tagForm input”).keypress(4 5 function(event){6 7 if(event.keyCode 13){8 9 returnfalse;10 11 }12 13 });14 15 })转载于:https://www.cnblogs.com/pfs1314/archive/2011/04/19/2020706.html

滑坡泥石流的防御措施_滑坡泥石流防御

什么是滑坡、泥石流?滑坡是指山坡在河流冲刷、降雨、地震、人工切坡等因素影响下&#xff0c;土层或岩层整体或分散地顺斜坡向下滑动的现象。滑坡也叫地滑&#xff0c;群众中还有“走山”、“垮山”或“山剥皮”等俗称。泥石流是指在降水、溃坝或冰雪融化形成的地面流水作用下…

Event Delegate(代理)异常:该委托必须有一个目标 解决方法

正文待叙转载于:https://www.cnblogs.com/kodong/archive/2013/04/19/3031212.html

自定义注解 实现自定义消息_实现自定义的未来

自定义注解 实现自定义消息上一次我们学习了java.util.concurrent.Future<T>背后的原理 。 我们还发现&#xff0c; Future<T>通常由库或框架返回。 但是&#xff0c;没有什么可以阻止我们在有意义的情况下自行实现所有功能。 它不是特别复杂&#xff0c;可以显着改…

菜单 java_java 菜单

继承体系MenuBar,Menu,MenuItem之间的关系&#xff1a;先创建菜单条&#xff0c;再创建菜单&#xff0c;每一个菜单中建立菜单项。也可以菜单添加到菜单中&#xff0c;作为子菜单。通过setMenuBar()方法&#xff0c;将菜单添加到Frame中。package june610;import java.awt.File…

Jsp、Servlet

1 forward、redirect forward 转发是服务器行为&#xff0c;浏览器根本不知道服务器发送的内容是从哪儿来&#xff0c;所以它的地址栏中还是原来的地址。 redirect 重定向是客户端行为。redirect就是服务端根据逻辑,发送一个状态码,告诉浏览器重新去请求那个地址&#xff0c;一…

Java Finalizer和Java文件输入/输出流

在与主题直接合作或花时间学习它们之后&#xff0c;我经常会发现自己在网上注意到更多主题。 最近的Stephen Connolly &#xff08; CloudBees &#xff09;发表FileInputStream / FileOutputStream被认为有害的消息引起了我的注意&#xff0c;因为我最近在Java的finalizer中遇…

java 运行main_使用maven运行Java Main的三种方法解析

maven使用exec插件运行java main方法&#xff0c;以下是3种不同的操作方式。一、从命令行运行1、运行前先编译代码&#xff0c;exec&#xff1a;java不会自动编译代码&#xff0c;你需要手动执行mvn compile来完成编译。mvn compile2、编译完成后&#xff0c;执行exec运行main方…

CentOS7 修复boot目录

这里为了达到实验目的&#xff0c;首先删除boot目录下所有内容 重启后发现系统进不去了&#xff0c;这正是我们想要的 进入系统救援模式&#xff0c;以重新引导系统 进入救援模式后&#xff0c;输入以下命令进行修复boot目录 重启后&#xff0c;能正常引导系统了 转载于:https:…

java corepoolsize_理解ThreadPoolExecutor线程池的corePoolSize、maximumPoolSize和poolSize

我们知道&#xff0c;受限于硬件、内存和性能&#xff0c;我们不可能无限制的创建任意数量的线程&#xff0c;因为每一台机器允许的最大线程是一个有界值。也就是说ThreadPoolExecutor管理的线程数量是有界的。线程池就是用这些有限个数的线程&#xff0c;去执行提交的任务。然…

开式蓄冷罐与闭式蓄冷罐_一罐来统治所有人

开式蓄冷罐与闭式蓄冷罐跳下内存通道 早在1998年&#xff0c;当我是一名C / C 开发人员时&#xff0c;尝试使用Java时&#xff0c;有关该语言的一些内容对我来说就显得有些恼火了。 我记得很担心这些 为什么没有合适的编辑器呢&#xff1f; C / C 有很多。 我为Java拥有的只是…

嵊州D5T2 折纸 folding

折纸 folding 【问题描述】 在非常紧张的 NOIP 考试中&#xff0c;有人喜欢啃指甲&#xff0c;有人喜欢转铅笔&#xff0c;有人喜欢撕 纸条&#xff0c;……而小 x 喜欢迷折纸。 现有一个 W * H 的矩形纸张&#xff0c;监考老师想知道&#xff0c;小 x 至少要折多少次才能使 矩…

使用Portworx和Couchbase的有状态容器

容器本应是短暂的&#xff0c;因此可以很好地扩展以用于无状态应用程序。 有状态的容器&#xff08;例如Couchbase&#xff09;需要区别对待。 管理Docker容器的持久性概述了如何管理有状态容器的持久性。 该博客将说明如何使用Docker Volume Plugins和Portworx创建有状态的容…

java和jvm_java 和 JVM

C和Java的区别指针&#xff1a;java中不存在指针的概念&#xff0c;编程者无法直接通过指针来直接访问内存&#xff0c;有利于维护java程序的安全多重继承&#xff1a;C支持多重继承&#xff0c;java不支持多重继承&#xff0c;但是允许一个类继承多个接口来实现多重继承的问题…

Redis 集群_主从复制_哨兵模型

1 redis集群简介 1.1 集群的概念 所谓的集群&#xff0c;就是通过添加服务器的数量&#xff0c;提供相同的服务&#xff0c;从而让服务器达到一个稳定、高效的状态。 1.1.1 使用redis集群的必要性 问题&#xff1a;我们已经部署好了redis&#xff0c;并且能启动一个redis&#…