在多线程和多进程环境下分别执行数字的累加操作.
2. 实验环境
- 电脑环境:实验室台式计算机
- 系统环境: Ubuntu 18.04 LTS
- 运行: Ubuntu terminal
3. 程序设计
3.1 多线程
3.1.1 流程图
3.1.2 描述
程序读取input.txt文件中的内容,赋值给N(线程数目)和M(累加值),检查参数N和M和合法性,若不合法则退出程序,反之继续运行,然后开启N个线程,每个线程的函数体流程如上,代码如下:
voidthreadSum(){while(count<=M){pthread_mutex_lock(&mutex);if(count<=M){sum+=count++;}pthread_mutex_unlock(&mutex);}}
主线程通过pthread_join等待子线程结束,然后输出结果到output.txt.
3.2 多进程
3.2.1 流程图
3.2.2 描述
程序读取input.txt文件中的内容,赋值给N(子进程数目)和M(累加值),检查参数N和M和合法性,若不合法则退出程序,反之继续运行,然后申请共享内存,并初始化信号量,然后开启N个子进程,每个子进程的函数体流程如上,代码如下:
while(pProcess->count<=M){sem_wait(&pProcess->S);if(pProcess->count<=M){pProcess->sum+=pProcess->count++;}sem_post(&pProcess->S);}
父进程等待子进程退出,然后销毁信号量,将结果输出到output.txt.
4. 结果分析
4.1 多线程
如下系列图所示,横坐标为线程数量,纵坐标为运行时间(单位us),不同折线表示不同计数量(图片通过python调用C程序使用matplotlib库画出)。
由上图可发现,开启相同线程数量时,累加的计数越大耗时越长(实验所用的主机电脑性能有些差,运行时间较长);
当线程数量为1时,运行相同计数量所耗时最少,因为当开启多个线程时,需要耗时开启线程,同时由于线程阻塞,也需要耗费一些时间,在内核态和用户态之间的切换很大程度地影响了程序的性能。但多线程时,所做的计数工作与单线程其实是一样的,而线程的阻塞反而影响了性能。
4.2 多进程
如下系列图所示,横坐标为进程数量,纵坐标为运行时间(单位us),不同折线表示不同计数量(图片通过python调用C程序使用matplotlib库画出)。
由上图可发现,开启相同进程数量时,累加的计数越大耗时越长(实验所用的主机电脑性能有些差,运行时间较长);
当进程数量为1时,运行相同计数量所耗时最少,因为当开启多个进程时,需要耗时开启进程,同时由于PV操作使得进程阻塞,也需要耗费一些时间,但多进程时,所做的计数工作与单进程其实是一样的,而进程的阻塞反而影响了性能。
同时,对比多线程和多进程下相同条件(相同线程/进程数量,相同计数值)下,多进程耗费的时间更长,因为对操作系统来说,开启一个线程比fork一个子进程所耗费的时间短许多。因为线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源比如说程序计数器等,而进程有独立的地址空间,进程切换时,耗费资源较大,所以效率要差一些。