OpenMP 《并行程序设计导论》的补充代码
▶ 使用 OpenMP 和队列数据结构,在各线程之间传递信息
● 代码,使用 critical 子句和 atomic 指令来进行读写保护
// queue.h
#ifndef _QUEUE_H_
#define _QUEUE_H_ struct queue_node_s // 定义队列结点,包含信息来源,信息内容,下一个结点的指针
{
int src;
int mesg;
struct queue_node_s* next_p;
}; struct queue_s // 定义队列,包含入队数,出队数,头尾指针
{
int enqueued;
int dequeued;
struct queue_node_s* front_p;
struct queue_node_s* tail_p;
}; struct queue_s* Allocate_queue(void);
void Free_queue(struct queue_s* q_p);
void Print_queue(struct queue_s* q_p);
void Enqueue(struct queue_s* q_p, int src, int mesg);
int Dequeue(struct queue_s* q_p, int* src_p, int* mesg_p);
int Search(struct queue_s* q_p, int mesg, int* src_p);
#endif // queue.c
#include <stdio.h>
#include <stdlib.h>
#include "queue.h" #ifdef USE_MAIN
int main(void)//检验函数
{
char op;
int src, mesg;
struct queue_s *q_p = Allocate_queue();
for (printf("Op? (e, d, p, s, f, q)\n"), scanf(" %c", &op); op != 'q' && op != 'Q'; printf("Op? (e, d, p, s, f, q)\n"), scanf(" %c", &op));
{
switch (op)
{
case 'e':
case 'E':
printf("Src? Mesg?\n");
scanf("%d%d", &src, &mesg);
Enqueue(q_p, src, mesg);
break;
case 'd':
case 'D':
if (Dequeue(q_p, &src, &mesg))
printf("Dequeued src = %d, mesg = %d\n", src, mesg);
else
printf("Queue is empty\n");
break;
case 's':
case 'S':
printf("Mesg?\n");
scanf("%d", &mesg);
if (Search(q_p, mesg, &src))
printf("Found %d from %d\n", mesg, src);
else
printf("Didn't find %d\n", mesg);
break;
case 'p':
case 'P':
Print_queue(q_p);
break;
case 'f':
case 'F':
Free_queue(q_p);
break;
default:
printf("%c isn't a valid command\n", op);
printf("Please try again\n");
}
}
Free_queue(q_p);
free(q_p);
return ;
}
#endif struct queue_s* Allocate_queue()// 创建队列
{
struct queue_s *q_p = malloc(sizeof(struct queue_s));
q_p->enqueued = q_p->dequeued = ;
q_p->front_p = q_p->tail_p = NULL;
return q_p;
} void Free_queue(struct queue_s* q_p)// 释放队列
{
struct queue_node_s *curr_p, *temp_p;
for (curr_p = q_p->front_p; curr_p != NULL; temp_p = curr_p, curr_p = curr_p->next_p, free(temp_p));
q_p->enqueued = q_p->dequeued = ;
q_p->front_p = q_p->tail_p = NULL;
} void Print_queue(struct queue_s* q_p)// 打印队列
{
struct queue_node_s *curr_p;
printf("queue = \n");
for (curr_p = q_p->front_p; curr_p != NULL; curr_p = curr_p->next_p)
printf(" src = %d, mesg = %d\n", curr_p->src, curr_p->mesg);
printf("enqueued = %d, dequeued = %d\n", q_p->enqueued, q_p->dequeued);
printf("\n");
} void Enqueue(struct queue_s* q_p, int src, int mesg)// 入队,按信息 src 和 mesg 向队列 q_p 添加结点
{
struct queue_node_s *n_p = malloc(sizeof(struct queue_node_s));
n_p->src = src;
n_p->mesg = mesg;
n_p->next_p = NULL;
if (q_p->tail_p == NULL)
{
q_p->front_p = n_p;
q_p->tail_p = n_p;
}
else
{
q_p->tail_p->next_p = n_p;
q_p->tail_p = n_p;
}
q_p->enqueued++;
} int Dequeue(struct queue_s* q_p, int* src_p, int* mesg_p)// 出队,信息放入 src_p 和 mesg_p
{
struct queue_node_s* temp_p;
if (q_p->front_p == NULL)
return ;
*src_p = q_p->front_p->src;
*mesg_p = q_p->front_p->mesg;
temp_p = q_p->front_p;
if (q_p->front_p == q_p->tail_p)
q_p->front_p = q_p->tail_p = NULL;
else
q_p->front_p = temp_p->next_p;
free(temp_p);
q_p->dequeued++;
return ;
} int Search(struct queue_s* q_p, int mesg, int* src_p)// 查找操作
{
struct queue_node_s *curr_p;
for (curr_p = q_p->front_p; curr_p != NULL; curr_p = curr_p->next_p)
{
if (curr_p->mesg == mesg)
{
*src_p = curr_p->src;
return ;
}
}
return ;
} // omp_msgps.c
#include <stdio.h>
#include <stdlib.h>
#include <omp.h>
#include "queue.h" const int MAX_MSG = ; void Usage(char *prog_name)// 输入参数错误时提示信息
{
fprintf(stderr, "usage: %s <number of threads> <number of messages>\n", prog_name);
fprintf(stderr, " number of messages = number sent by each thread\n");
getchar();
exit();
} void Send_msg(struct queue_s* msg_queues[], int my_rank, int thread_count, int msg_number)// 发送信息给 dest 的队列
{
int mesg = rand() % MAX_MSG;// int mesg = -msg_number;
int dest = rand() % thread_count;
# pragma omp critical
Enqueue(msg_queues[dest], my_rank, mesg);
# ifdef DEBUG
printf("Thread %d > sent %d to %d\n", my_rank, mesg, dest);
# endif
} void Try_receive(struct queue_s* q_p, int my_rank)// 如果队列 q_p 不空,则接受信息
{
int src, mesg;
int queue_size = q_p->enqueued - q_p->dequeued;
if (queue_size == )
return;
else if (queue_size == )
# pragma omp critical
Dequeue(q_p, &src, &mesg);
else
Dequeue(q_p, &src, &mesg);
printf("Thread %d > received %d from %d\n", my_rank, mesg, src);
} int Done(struct queue_s* q_p, int done_sending, int thread_count)// 检查是否空队
{
int queue_size = q_p->enqueued - q_p->dequeued;
if (queue_size == && done_sending == thread_count)
return ;
return ;
} int main(int argc, char* argv[])
{
int thread_count, send_max, done_sending;
struct queue_s** msg_queues;
if (argc != || (thread_count = strtol(argv[], NULL, )) <= || (send_max = strtol(argv[], NULL, ) < ))
Usage(argv[]);
msg_queues = malloc(thread_count * sizeof(struct queue_node_s*));
done_sending = ; # pragma omp parallel num_threads(thread_count) default(none) shared(thread_count, send_max, msg_queues, done_sending)
{
int my_rank = omp_get_thread_num(), msg_number;
srand(my_rank);
msg_queues[my_rank] = Allocate_queue(); # pragma omp barrier// 等待所有线程都建好队列在开始收发信息 for (msg_number = ; msg_number < send_max; msg_number++)// 每个线程都发送 send_max 个信息
{
Send_msg(msg_queues, my_rank, thread_count, msg_number);
Try_receive(msg_queues[my_rank], my_rank);
}
# pragma omp atomic
done_sending++;
# ifdef DEBUG
printf("Thread %d > done sending\n", my_rank);
# endif while (!Done(msg_queues[my_rank], done_sending, thread_count))
Try_receive(msg_queues[my_rank], my_rank); Free_queue(msg_queues[my_rank]);
free(msg_queues[my_rank]);
}
free(msg_queues);
getchar();
return ;
}
● 代码,使用 omp 锁来进行读写保护
// queue_lk.h
#ifndef _QUEUE_LK_H_
#define _QUEUE_LK_H_
#include <omp.h> struct queue_node_s
{
int src;
int mesg;
struct queue_node_s* next_p;
}; struct queue_s// 定义队列,多一个 omp_lock_t
{
omp_lock_t lock;
int enqueued;
int dequeued;
struct queue_node_s* front_p;
struct queue_node_s* tail_p;
}; struct queue_s* Allocate_queue(void);
void Free_queue(struct queue_s* q_p);
void Print_queue(struct queue_s* q_p);
void Enqueue(struct queue_s* q_p, int src, int mesg);
int Dequeue(struct queue_s* q_p, int* src_p, int* mesg_p);
int Search(struct queue_s* q_p, int mesg, int* src_p);
#endif // queue_lk.c
#include <stdio.h>
#include <stdlib.h>
#include <omp.h>
#include "queue_lk.h" #ifdef USE_MAIN
int main(void)
{
char op;
int src, mesg, not_empty;
struct queue_s *q_p = Allocate_queue();
for (printf("Op? (e, d, p, s, f, q)\n"), scanf(" %c", &op); op != 'q' && op != 'Q'; printf("Op? (e, d, p, s, f, q)\n"), scanf(" %c", &op))
{
switch (op)
{
case 'e':
case 'E':
printf("Src? Mesg?\n");
scanf("%d%d", &src, &mesg);
omp_set_lock(&q_p->lock);// DIFF
Enqueue(q_p, src, mesg);
omp_unset_lock(&q_p->lock);
break;
case 'd':
case 'D':
omp_set_lock(&q_p->lock);// DIFF,注意把出队放在锁中间,而判断空队则是在释放锁以后进行
not_empty = Dequeue(q_p, &src, &mesg);
omp_unset_lock(&q_p->lock);
if (not_empty)
printf("Dequeued src = %d, mesg = %d\n", src, mesg);
else
printf("Queue is empty\n");
break;
case 's':
case 'S':
printf("Mesg?\n");
scanf("%d", &mesg);
if (Search(q_p, mesg, &src))
printf("Found %d from %d\n", mesg, src);
else
printf("Didn't find %d\n", mesg);
break;
case 'p':
case 'P':
Print_queue(q_p);
break;
case 'f':
case 'F':
omp_set_lock(&q_p->lock);// DIFF
Free_queue(q_p);
omp_unset_lock(&q_p->lock);
break;
default:
printf("%c isn't a valid command\n", op);
printf("Please try again\n");
}
}
Free_queue(q_p);
omp_destroy_lock(&q_p->lock);// DIFF
free(q_p);
return ;
}
#endif struct queue_s* Allocate_queue()
{
struct queue_s *q_p = malloc(sizeof(struct queue_s));
q_p->enqueued = q_p->dequeued = ;
q_p->front_p = q_p->tail_p = NULL;
omp_init_lock(&q_p->lock);// DIFF
return q_p;
} void Free_queue(struct queue_s* q_p)
{
struct queue_node_s *curr_p, *temp_p;
for (curr_p = q_p->front_p; curr_p != NULL; temp_p = curr_p, curr_p = curr_p->next_p, free(temp_p));
q_p->enqueued = q_p->dequeued = ;
q_p->front_p = q_p->tail_p = NULL;
} void Print_queue(struct queue_s* q_p)
{
struct queue_node_s *curr_p;
printf("queue = \n");
for (curr_p = q_p->front_p; curr_p != NULL; curr_p = curr_p->next_p)
printf(" src = %d, mesg = %d\n", curr_p->src, curr_p->mesg);
printf("enqueued = %d, dequeued = %d\n", q_p->enqueued, q_p->dequeued);
printf("\n");
} void Enqueue(struct queue_s* q_p, int src, int mesg)
{
struct queue_node_s *n_p = malloc(sizeof(struct queue_node_s));
n_p->src = src;
n_p->mesg = mesg;
n_p->next_p = NULL;
if (q_p->tail_p == NULL)
{
q_p->front_p = n_p;
q_p->tail_p = n_p;
}
else
{
q_p->tail_p->next_p = n_p;
q_p->tail_p = n_p;
}
q_p->enqueued++;
} int Dequeue(struct queue_s* q_p, int* src_p, int* mesg_p)
{
struct queue_node_s* temp_p;
if (q_p->front_p == NULL)
return ;
*src_p = q_p->front_p->src;
*mesg_p = q_p->front_p->mesg;
temp_p = q_p->front_p;
if (q_p->front_p == q_p->tail_p)
q_p->front_p = q_p->tail_p = NULL;
else
q_p->front_p = temp_p->next_p;
free(temp_p);
q_p->dequeued++;
return ;
} int Search(struct queue_s* q_p, int mesg, int* src_p)
{
struct queue_node_s *curr_p;
for (curr_p = q_p->front_p; curr_p != NULL; curr_p = curr_p->next_p)
{
if (curr_p->mesg == mesg)
{
*src_p = curr_p->src;
return ;
}
}
return ;
} // omp_msglk.c
#include <stdio.h>
#include <stdlib.h>
#include <omp.h>
#include "queue_lk.h" const int MAX_MSG = ; void Usage(char *prog_name)
{
fprintf(stderr, "usage: %s <number of threads> <number of messages>\n", prog_name);
fprintf(stderr, " number of messages = number sent by each thread\n");
getchar();
exit();
} void Send_msg(struct queue_s* msg_queues[], int my_rank, int thread_count, int msg_number)
{
int mesg = random() % MAX_MSG;// int mesg = -msg_number;
int dest = random() % thread_count;
struct queue_s* q_p = msg_queues[dest];
omp_set_lock(&q_p->lock);// DIFF
Enqueue(q_p, my_rank, mesg);
omp_unset_lock(&q_p->lock);
# ifdef DEBUG
printf("Thread %d > sent %d to %d\n", my_rank, mesg, dest);
# endif
} void Try_receive(struct queue_s* q_p, int my_rank)
{
int src, mesg;
int queue_size = q_p->enqueued - q_p->dequeued;
if (queue_size == )
return;
else if (queue_size == )
{
omp_set_lock(&q_p->lock);// DIFF
Dequeue(q_p, &src, &mesg);
omp_unset_lock(&q_p->lock);
}
else
Dequeue(q_p, &src, &mesg);
printf("Thread %d > received %d from %d\n", my_rank, mesg, src);
} int Done(struct queue_s* q_p, int done_sending, int thread_count)
{
int queue_size = q_p->enqueued - q_p->dequeued;
if (queue_size == && done_sending == thread_count)
return ;
return ;
} int main(int argc, char* argv[])
{
int thread_count, send_max, done_sending;
struct queue_s** msg_queues;
if (argc != || (thread_count = strtol(argv[], NULL, )) <= || (send_max = strtol(argv[], NULL, ) < ))
Usage(argv[]);
msg_queues = malloc(thread_count * sizeof(struct queue_node_s*));
done_sending = ; # pragma omp parallel num_threads(thread_count) default(none) shared(thread_count, send_max, msg_queues, done_sending)
{
int my_rank = omp_get_thread_num(), msg_number;
srand(my_rank);
msg_queues[my_rank] = Allocate_queue(); # pragma omp barrier for (msg_number = ; msg_number < send_max; msg_number++)
{
Send_msg(msg_queues, my_rank, thread_count, msg_number);
Try_receive(msg_queues[my_rank], my_rank);
}
# pragma omp atomic
done_sending++;
# ifdef DEBUG
printf("Thread %d > done sending\n", my_rank);
# endif while (!Done(msg_queues[my_rank], done_sending, thread_count))
Try_receive(msg_queues[my_rank], my_rank); Free_queue(msg_queues[my_rank]);
free(msg_queues[my_rank]);
}
free(msg_queues);
getchar();
return ;
}
OpenMP 《并行程序设计导论》的补充代码的更多相关文章
- 《并行程序设计导论》——MPI(Microsoft MPI)(1):Hello
=================================版权声明================================= 版权声明:原创文章 禁止转载 请通过右侧公告中的“联系邮 ...
- OpenMP并行程序设计——for循环并行化详解
在C/C++中使用OpenMP优化代码方便又简单,代码中需要并行处理的往往是一些比较耗时的for循环,所以重点介绍一下OpenMP中for循环的应用.个人感觉只要掌握了文中讲的这些就足够了,如果想要学 ...
- OpenMP并行程序设计
1.fork/join并行执行模式的概念 2.OpenMP指令和库函数介绍 3.parallel 指令的用法 4.for指令的使用方法 5 sections和section指令的用法 1.fork/j ...
- OpenMP 并行程序设计入门
OpenMP 是一个编译器指令和库函数的集合,主要是为共享式存储计算机上的并行程序设计使用的. 0. 一段使用 OpenMP 的并行程序 #include <stdio.h> #inclu ...
- Pthreads 《并行程序设计导论》的补充代码
▶ 关于单链表的访问,插入结点和删除结点操作,并且将其推广到多线程中去. ● 代码,通用的随机数生成 // my_rand.h #ifndef _MY_RAND_H_ #define _MY_RAND ...
- 《并行程序设计导论》——OpenMP
OpenMP看着很好,实际上坑很多. 如果真的要求性能和利用率,还是专门写代码吧.而且MS的VS里只有2.X的版本.
- 《并行程序设计导论》——Pthreads
这部分不需要看了. 因为C++11和BOOST比这个Pthreads要好一点. 如果不考虑移植性,在Windows平台上用核心编程的东西比C++11和BOOST更好控制.
- 《并行程序设计导论》——MPI(Microsoft MPI)(6):并行排序算法
=================================版权声明================================= 版权声明:原创文章 禁止转载 请通过右侧公告中的“联系邮 ...
- openMP编程(上篇)之并行程序设计
openMP简介 openMP是一个编译器指令和库函数的集合,主要是为共享式存储计算机上的并行程序设计使用的. 当计算机升级到多核时,程序中创建的线程数量需要随CPU核数变化,如在CPU核数超过线程数 ...
随机推荐
- Java IO流-随机访问流
2017-11-05 19:45:51 RandomAccessFile类(随机访问流) RandomAccessFile类:是Object的子类,此类的实例支持对随机访问文件的读取和写入.随机访问文 ...
- 路由跟踪tracert
Tracert命令 如果我们要测试某一个IP都经过哪些路由,用trcert命令即可,这是dos下的一个基本网络命令,具体使用方法: 1,在windows系统下,打开 运行 :输入 cmd :在弹出的d ...
- idea 设置编译快捷键(代替 ctrl+f9)
问题描述 今日在设置项目热部署的时候,无奈就是不会自动编译,不知什么原因. 而编译的话,要么去点小按钮 ,要么使用ctrl + f9,实在不便. 且ctrl + f9目测不能更改. 解决办法 借鉴了关 ...
- 用Python操作Named pipe命名管道,实用做法——os.read 或 os.write
https://blog.csdn.net/mayao11/article/details/50618598
- jspf、jsp小记
jsp页面:
- POJ 3087 Shuffle'm Up 线性同余,暴力 难度:2
http://poj.org/problem?id=3087 设:s1={A1,A2,A3,...Ac} s2={Ac+1,Ac+2,Ac+3,....A2c} 则 合在一起成为 Ac+1,A1,Ac ...
- 【javascript基础】之【__lookupSetter__ 跟 __lookupSetter__】
描述: 返回getter setter所定义的函数 语法: obj.__lookupGetter__(sprop) 参数: getter setter中定义的字符串属性 注意:这不是标准的方法,ecm ...
- android中自定义view构造函数ContentItemView(Context context, AttributeSet paramAttributeSet)的用处
自己定义一个view <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:a ...
- iOS导航栏的正确隐藏方式
在项目中经常碰到首页顶部是无限轮播,需要靠最上面显示.有的设置导航栏为透明等一系列的方法,这个可以借助第三方.或者干脆简单粗暴的直接隐藏掉导航栏.可是push到下一个页面的时候是需要导航栏的,如何做了 ...
- css中用#id.class的形式定义样式,为什么这样用,不直接写成.class.代码如下:#skin_0.selected{}这种的
<ul class="skin"> <li id="skin_0" title="蓝色" class="sele ...