Linux下用线程pthread加速程序
来源:互联网 发布:mac恢复模式 terminal 编辑:程序博客网 时间:2024/05/16 12:23
自从上次写了数学之美之分形——C++及OpenCV实现Julia集和Mandelbrot集绘制,还有用OpenMP加速你的程序——以分形绘制为例之后,一直耿耿于怀啊,为什么不能自己实现多进程或者线程编程实现程序的加速呢。
终于,OS课程上学会了线程还有进程编程,现在,就以线程为例来实现程序的加速吧!
首先,得介绍下线程,Linux中的线程实际上就是轻量级的进程,CPU调度的时候是以线程调度的,而一个进程可以拥有多个线程,然后统一由内核统一调度。
(注意,Linux早期版本中没有实现线程,比如Linux0.11,只有进程,如果各位有兴趣,不妨试试自己去实现下内核级线程。)
然后是几个主要的线程库函数:
int pthread_attr_init(pthread_attr_t *attr);用默认值初始化attr指向的pthread_attr_t结构。pthread_attr_t主要定义了创建线程时需要用户提供的属性信息,pthread_create()根据这些信息创建线程。函数成功时返回0,出错时返回错误号。当然调用之后需要销毁, pthread_attr_destroy即可。int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg); 该函数用来创建一个线程。attr是创建线程时使用的各种属性,由pthread_attr_init()设定。当该线程被调度时会从函数start_routine(一段用户态代码)开始执行。arg做为参数被传递给start_routine。start_routine的原型为:void * start_routine(void *arg);如果线程创建成功,返回值0,并且把线程的ID值存放在thread中;当创建不成功时会返回一个错误号:EAGAIN表示系统缺乏足够的资源来创建线程,EINVAL表示attr结构中的属性值非法。当然,也可以用NULL代替attr的初始化,在需要知道attr的信息或者要修改的时候才去用pthread_attr_init函数void pthread_exit(void *value_ptr);将调用该函数的线程销毁。它没有返回值,因为调用它的线程已经销毁,所以返回值没有任何地方可以“返回”。value_ptr是传给父线程的返回值,父线程调用pthread_join()可得到这个值。这是线程主动终止的唯一方式。int pthread_join(pthread_t thread, void **value_ptr);将调用它的线程阻塞,一直等到thread结束为止。其中thread为被等待的线程ID,value_ptr会接收到被等待线程通过pthread_exit()设置的返回值。
具体相信内容以及其他更多函数请看POSIX Threads Programming
然后开始讲解代码,如果没看过前面几篇文章,建议去看下,因为下面的代码就是修改之前的之后提出来讲的:
1.必不可少的头文件
#include <pthread.h>
2.一些结构以及定义
#define THREAD_NUM 4typedef struct{ int start; int end; pthread_t ppid; pthread_attr_t attr_t;}task_struct;task_struct tasks[THREAD_NUM];
3.将原来的drawPic函数拆分:
void* draw_task(void* arg){double deltaX = (XMax - XMin) / width;double deltaY = (YMax - YMin) / height;//int max_iterations = 256;double max_size = 4.0; task_struct* t = (task_struct*)arg;for(int row = t->start;row < t->end;row++){for(int col = 0;col < width;col++){int color = 0;Complex c,z;z.real = 0;z.img = 0;c.real = XMin + col * deltaX;c.img = YMin + row * deltaY;//z.real = XMin + col * deltaX;//z.img = YMin + row * deltaY;//c.real = 0.285;//c.img = 0.01;while((color < MAX_COLOR) && ((z.img * z.img + z.real * z.real) < max_size)){double tmp = z.real * z.real - z.img * z.img + c.real;z.img = z.img * z.real * 2 + c.img;z.real = tmp;color++;}if(color == MAX_COLOR) { IMG_8UB(fractal,col,row) = 0; IMG_8UG(fractal,col,row) = 0; IMG_8UR(fractal,col,row) = 0; } else { IMG_8UB(fractal,col,row) = B[color]; IMG_8UG(fractal,col,row) = G[color]; IMG_8UR(fractal,col,row) = R[color]; }//color %= MAX_COLOR;}} pthread_attr_destroy(&(t->attr_t)); pthread_exit(NULL);}void drawPic(){ int step = height / THREAD_NUM; for(int i = 0;i < THREAD_NUM;i++) { tasks[i].start = i * step;//分配任务 tasks[i].end = tasks[i].start + step; if(i == THREAD_NUM - 1) tasks[i].end += height % THREAD_NUM; pthread_attr_init(&(tasks[i].attr_t)); if(pthread_create(&(tasks[i].ppid),&(tasks[i].attr_t),draw_task,(void*)&tasks[i]))//开始建立线程 printf("Error create pthread!\n"); } void* status; for(int i = 0;i < THREAD_NUM;i++) { if(!pthread_join(tasks[i].ppid,&status))//阻塞主线程,等待所有的子线程 printf("Thread %ld,exit with status %d\n",tasks[i].ppid,(int)status); else printf("Error when join\n"); } //cvCvtColor(fractal,fractal,CV_HSV2BGR); cvSaveImage(name[fileIndex++],fractal); cvShowImage("Fractal",fractal); cvCopy(fractal,fcopy); //cvWaitKey(0);}
然后,编译:对于线程函数,需要加上库-lpthread
g++ main.cpp -o main `pkg-config opencv --libs --cflags opencv` -lpthread
- Linux下用线程pthread加速程序
- Linux下pthread线程库介绍
- Linux下pthread线程库介绍
- Linux下pthread的线程亲和性研究
- linux下使用pthread库函数创建线程
- Linux下pthread的线程亲和性研究
- Linux线程pthread笔记
- Linux 线程 pthread
- linux pthread 线程库
- linux pthread线程详解
- linux pthread线程学习
- linux 线程 pthread
- linux pthread 线程详解
- Linux pthread 线程 浅解
- linux线程pthread互斥锁
- Linux Pthread线程详解
- linux socket聊天程序(线程版本pthread)
- Linux下调用pthread库实现简单线程池
- icePubDLL应用系列
- 大学生宿舍版《新闻联播》
- 策略模式
- 我要做的
- 对“缓存”的全面理解和优化
- Linux下用线程pthread加速程序
- 纯DIV+CSS左侧导航菜单(DIV溢出文字用省略号点代替)
- 如何在Linux下发布asp网站
- 上拉电阻下拉电阻的总结
- eclipse 编译和部署openfire
- UNIX 屏幕导向程序的发展利器-curses
- (2011.11.26)03_折半插入排序.cpp
- OpenCV自带例子(四)改变一张图片的对比度与亮度
- RSA 加密算法