为什么并行没有比串行快?
2013-01-05 18:29
204 查看
要统计一个整型数组中3出现的次数,写一个并行程序:
![](http://pic002.cnblogs.com/images/2012/103496/2012010316595864.png)
改进历史:
由于自加运行并不是原子操作,所以在每个线程中counter++前要获得互斥锁。
频繁地加锁和解锁会使运行效率降低。下面我们给每个线程一个私有的计数器private_counter,计算结束后一次性更新全局变量counter。
私有计数器private_counter从int演变为struct padded_int的原因是:int型的private_counter并不是真正私有的。cache一致性协议两个处理器看到的存储映象是相同的。cache一致性的单位是cache行,本机有cahche行大小是64字节(我猜是这样的,因为/proc/cpuinfo文件中写着:cache_alignment: 64 )。private_counter[0]和private_counter[1]被放在了同一个cache行中,对cache行中任一部分的修改等同于对整个cache行的修改。逻辑上不同的数据共享cache行的现象叫做假共享。所以当处理器1修改private_counter[0]之前,处理器2必须把自己手中相应的cache行废弃掉;当处理器1修改完private_counter[0]之后,处理器2再能重新获取private_counter[1]所在的cache行的操作权。为了不让private_counter[0]和private_counter[1]在同了个cache行内,所以把它们都填充成了64字节。
现在的体系结构已经可以把多线程映射到不同的处理器上,可为什么并行计算的速度还是没有串行的快呢?
#include<time.h> #include<assert.h> #include<stdlib.h> #include<stdio.h> #include<string.h> #include<sys/types.h> #include<pthread.h> #define ARRLEN 200000000 //int型数组的长度,我们的程序就是要统计这个数组中元素3出现了多少次 struct padded_int{ int value; //4个字节 char padding[60]; //60个字节 }*private_counter; int counter=0; int arr[ARRLEN]={0}; pthread_mutex_t lock=PTHREAD_MUTEX_INITIALIZER; int max_threads=0; //令最多开辟的线程数等于核数 /*用随机数初始化数组*/ void initArr(){ int i; for(i=0;i<ARRLEN;i++) arr[i]=rand()%1000; } /*从/proc/cpuinfo文件中获取CPU的核数*/ void getCoreNum(int *num){ FILE *fp; if((fp=fopen("/proc/cpuinfo","r"))==NULL){ perror("fopen"); exit(1); } int cn=0; char buf[256]; memset(buf,0x00,sizeof(buf)); while((fgets(buf,sizeof(buf),fp))!=NULL){ if(strstr(buf,"cpu cores")!=NULL){ char *delim=":"; char *tag=strtok(buf,delim); char *cn_str=strtok(NULL,delim); cn=atoi(cn_str); break; } memset(buf,0x00,sizeof(buf)); } fclose(fp); *num=cn; printf("您的计算机是%d核的\n",cn); } /*每个线程负责统计数组的一段区域内3出现的次数*/ void *count_thread(void* id){ int index=*(int *)id; assert(max_threads!=0); int section_len=ARRLEN/max_threads; int start=index*section_len; int i; for(i=start;i<start+section_len;i++){ if(arr[i]==3){ private_counter[index].value++; } } printf("private_counter[%d].value=%d\n",index,private_counter[index].value); pthread_mutex_lock(&lock); counter+=private_counter[index].value; pthread_mutex_unlock(&lock); } /*串行方法统计3出现的次数*/ void count(){ counter=0; int i; for(i=0;i<ARRLEN;i++) if(arr[i]==3) counter++; } /*主函数*/ main(){ initArr(); getCoreNum(&max_threads); counter=0; clock_t t1=clock(); pthread_t *pths; private_counter=(struct padded_int*)calloc(2,sizeof(struct padded_int)); pths=(pthread_t*)calloc(max_threads,sizeof(pthread_t)); int i; for(i=0;i<max_threads;i++) //开辟多线程分头工作 pthread_create(pths+i,NULL,count_thread,(void*)&i); for(i=0;i<max_threads;i++) //等待所有子线程收工 pthread_join(*(pths+i),NULL); free(private_counter); free(pths); printf("并行计算的结果:%d\n",counter); clock_t t2=clock(); count(); printf("串行计算结果:%d\n",counter); clock_t t3=clock(); printf("并行计算用时:%.2f秒\n",((double)(t2-t1)/CLOCKS_PER_SEC)); printf("串行计算用时:%.2f秒\n",((double)(t3-t2)/CLOCKS_PER_SEC)); }
![](http://pic002.cnblogs.com/images/2012/103496/2012010316595864.png)
改进历史:
由于自加运行并不是原子操作,所以在每个线程中counter++前要获得互斥锁。
频繁地加锁和解锁会使运行效率降低。下面我们给每个线程一个私有的计数器private_counter,计算结束后一次性更新全局变量counter。
私有计数器private_counter从int演变为struct padded_int的原因是:int型的private_counter并不是真正私有的。cache一致性协议两个处理器看到的存储映象是相同的。cache一致性的单位是cache行,本机有cahche行大小是64字节(我猜是这样的,因为/proc/cpuinfo文件中写着:cache_alignment: 64 )。private_counter[0]和private_counter[1]被放在了同一个cache行中,对cache行中任一部分的修改等同于对整个cache行的修改。逻辑上不同的数据共享cache行的现象叫做假共享。所以当处理器1修改private_counter[0]之前,处理器2必须把自己手中相应的cache行废弃掉;当处理器1修改完private_counter[0]之后,处理器2再能重新获取private_counter[1]所在的cache行的操作权。为了不让private_counter[0]和private_counter[1]在同了个cache行内,所以把它们都填充成了64字节。
现在的体系结构已经可以把多线程映射到不同的处理器上,可为什么并行计算的速度还是没有串行的快呢?
相关文章推荐
- 为什么说串行比并行快
- 串行总线硬盘为什么比并行总线硬盘快?
- 串行总线硬盘为什么比并行总线硬盘快?
- 串行总线硬盘为什么比并行总线硬盘快?
- 为什么说串行比并行快?
- Windows Server 2012 为什么没有“磁盘清理”选项了?
- 我的onServiceDisconnected为什么没有被呼叫
- 为什么银行有取号机而超市结账的时候没有
- 为什么xcode6没有自动创建pch文件呢?(不小心删除了.pch文件 该如何添加)
- 为什么core开关打开了, 没有产生core文件呢?------又是磁盘文件满了
- Python串行运算、并行运算、多线程、多进程对比实验
- Eclipse的工程发布到tomcat下,为什么webapps什么都没有????????
- 没有安全感的IT员工--为什么容易“集体跳槽”
- 为什么我的程序中没有stdafx.h头文件?
- c++ 为什么没有垃圾回收机制
- 自定义的token为什么没有写入cookie中?
- JavaSE中线程与并行API框架学习笔记——线程为什么会不安全?
- (转载)java的main函数为什么没有返回值
- xgboost相比传统gbdt有何不同?xgboost为什么快?xgboost如何支持并行?