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

本文介绍了如何使用多线程计算数组元素的和,并通过实验展示了随着线程数量增加,性能的变化。代码中为了避免线程安全问题,采用可重入函数实现。测试结果显示,在四核处理器(双核心四线程)上,当线程数超过4时,性能提升不再明显,验证了处理器的线程处理能力。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

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 100

int 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是一台四核的计算机。我们去网页上查了一查,发现是双核心四线程电脑,也就是说有超线程技术,所以可以同时处理四个线程,但是处理四线程因为超线程了,所以比双线程快不了多少,所以是双核心四线程计算机,与测量结果吻合。所以这个代码不仅可以求数组元素的和,还可以用来测量计算机的线程数。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值