利用多线程计算元素数组的和

来源:互联网 发布:天涯明月刀数据异常 编辑:程序博客网 时间:2024/05/18 19:46

利用多线程计算元素数组的和

CS:APP有一章节讲的是多线程,里面有一个例子讲的是利用多线程可重入地计算数组元素的和。因为加法满足交换率,多线程计算数组元素的和再相加数学上是正确的。
首先一开始想写一个共享变量sum,所有线程都往sum上加,后来发现这样必须加锁,不然存在很严重的线程不安全问题,但是256个锁…画面太美不敢看,所以干脆写成可重入的函数了。


以下为代码:为了方便测量性能,我们令每一次加法内部做无用功浪费一点时间。所以编译起来有两个问题,一是不能开-O1,-O2,因为会把无用代码优化调,所以开-O0,二是一定要加-pthread。因为 pthread.h不是Linux默认静态库。

#include<stdio.h>#include<stdlib.h>#include<pthread.h>#include<time.h>#define LEN 2560000#define N 256#define TIMES 100#define WASTE 100int data[LEN];int sum[N];int ans;void init(){    ans=0;    for (int i=0;i<N;i++)        sum[i]=0;    for (int i=0;i<LEN;i++)        data[i]=1;    return;}void dosomething(){    for (int i=0;i<WASTE;i++);    return;}void* thread(void* vargp){    int k=((int*) vargp)[0];    int n=((int*) vargp)[1];    for (int i=k*LEN/n;i<(k+1)*LEN/n;i++)        for (int j=0;j<TIMES;j++)        {            sum[k]+=data[i];            dosomething();        }    return NULL;}int main(){    int* ptr;    int var[N][2];    int cpe,cpe1;    pthread_t tid[N];    time_t t1,t2;     for (int n=1;n<=N;n=n*2)    {        time(&t1);        init();        for (int i=0;i<n;i++)        {            var[i][0]=i;            var[i][1]=n;            pthread_create(&tid[i],NULL,thread,(void*)var[i]);          }        for (int i=0;i<n;i++)            pthread_join(tid[i],NULL);        for (int i=0;i<n;i++)            ans+=sum[i];        if (ans!=LEN*TIMES)        {            printf("Wrong Answer!\n");            printf("ans=%d(but it should be %d!)\n",ans,LEN*TIMES);            exit(1);        }        time(&t2);        cpe=TIMES*LEN/((int)(t2-t1))/1000;        if (n==1)            cpe1=cpe;        printf("%3d threads:time=%2d,CPE=%dK,acc rate=%.3f\n",            n,(int)(t2-t1),cpe,((float)cpe)/cpe1);    }    exit(0);}

测试结果(CPE是一个相对参数,没有单位,大致指的是每一个元素处理的时间代价)

zzy@zzy-lenovo-g50-80:~/zzy/project/ICS/pthread$ ./psum
1 threads:time=64,CPE=4000K,acc rate=1.000
2 threads:time=34,CPE=7529K,acc rate=1.882
4 threads:time=29,CPE=8827K,acc rate=2.207
8 threads:time=27,CPE=9481K,acc rate=2.370
16 threads:time=27,CPE=9481K,acc rate=2.370
32 threads:time=27,CPE=9481K,acc rate=2.370
64 threads:time=26,CPE=9846K,acc rate=2.461
128 threads:time=27,CPE=9481K,acc rate=2.370
256 threads:time=26,CPE=9846K,acc rate=2.461

我们可以发现线程多于4个时候acc rate不再上升,也就是说很有可能zzy-lenovo-g50-80是一台四核的计算机。我们去网页上查了一查,发现是双核心四线程电脑,也就是说有超线程技术,所以可以同时处理四个线程,但是处理四线程因为超线程了,所以比双线程快不了多少,所以是双核心四线程计算机,与测量结果吻合。所以这个代码不仅可以求数组元素的和,还可以用来测量计算机的线程数。

0 0
原创粉丝点击