LinuxC多线程求和

我们要实现的是,使用多线程来计算 1 ~ n 范围的所有整数和。

计算运行时间

  因为要将普通求和程序与多线程作比较,所以先介绍一下如何计算程序运行的时间。

获取时间函数

#include<sys/time.h>

int gettimeofday(struct timeval*tv, struct timezone *tz);

参数

其参数tv是保存获取时间结果的结构体,参数tz用于保存时区结果。tz 一般为NULL即可。

struct timezone{
int tz_minuteswest;/*格林威治时间往西方的时差*/
int tz_dsttime;/*DST 时间的修正方式*/
}

struct timeval{
long int tv_sec; // 秒数
long int tv_usec; // 微秒数
}

因为上面获取到的时间,拆分为了秒级和微秒两部分,我们需要将他们组合成一个准确的时间。下面是我自定义的函数:

double get_time()
{
    struct timeval t;
    gettimeofday(&t,NULL);
    return t.tv_sec + t.tv_usec/1000000.0;
}

下面进入正题~

多线程求和

比如,我们要计算1到100的整数和,可以将这100个数分为2部分,利用线程并行的特点,同时计算这两部分整数的和,线程1计算1到50,线程2计算51到100,最后将这两部分和在相加。听起来是不是效率变快了一半。

下面我们测试一下,计算 1~100000000的和

//编译的warning不用理会
#include<stdio.h>
#include<stdlib.h>
#include<pthread.h>

#define MAX     1000000000    //整数范围 1 ~ MAX
#define N       100           //创建N 个子线程求和
#define AVE     (MAX/N)       //每个子线程处理的整数个数

long long     *sum = NULL;    //保存各个子线程计算的结果

//获取当前时间
double get_time()
{
    struct timeval t;
    gettimeofday(&t,NULL);
    return t.tv_sec + t.tv_usec/1000000.0;
}

//求和子线程
void* sum_work(void* arg)
{
    int            n = (int)arg;  //第n部分
    long long      start = n*AVE+1;
    long long      end = start + AVE -1;
    long long      i;
    sum[n] = 0;

    //计算start ~ end 范围的整数和
    for(i=start; i <= end;i++)
    {
        sum[n] = sum[n] + i;
    }
    pthread_exit(0);
}

int main()
{
    double         t1,t2;
    pthread_t      *pthread_id = NULL; //保存子线程id
    int            i;
    long long      result = 0;         //总和

    pthread_id = (pthread_t*)malloc(N * sizeof(pthread_t));
    sum  = (long long*)malloc(N * sizeof(long long));

    //开始计算
    t1 = get_time();

    //创建N个子线程
    for(i=0;i<N;i++)
    {
        pthread_create(pthread_id+i,NULL,sum_work,i);
    }

    //将各个子线程的求和结果综合到一起
    for(i=0;i<N;i++)
    {
        //等待子线程结束,如果该子线程已经结束,则立即返回
        pthread_join(pthread_id[i],NULL);
        result += sum[i];
    }

    //求和结束
    t2 = get_time();

    //输出求和结果和运行时间
    printf("sum of 1 ~ %lld is %lld runtime is %f\n",(long long)MAX,result,t2-t1);

    free(pthread_id);
    free(sum);
    return 0;
}

运行结果:5组数据平均1.14秒

这里写图片描述

扫描二维码关注公众号,回复: 2890302 查看本文章

不用多线程的一般求和程序

#include<stdio.h>
#include<sys/time.h>

#define MAX     1000000000

double get_time()
{
    struct timeval t;
    gettimeofday(&t,NULL);
    return t.tv_sec + t.tv_usec/1000000.0;
}

int main()
{
    double       t1, t2;
    long long    i;
    long long    sum = 0;

    t1 = get_time();

    for(i =1;i<=MAX;i++)
    {
        sum += i;
    }

    t2 = get_time();

    printf("sum of 1 ~ %lld is %lld  runtime is %f\n",(long long)MAX,sum,t2-t1);
    return 0;
}

运行结果:同样5组数据平均2.62秒

这里写图片描述

可以看出,与多线程比较差距很明显。

但是,如果将求和的范围缩小,比如将上面的MAX值调成1000,再次运行就会发现多线程计算的时间要比普通程序长了。为什么呢?因为当计算的整数比较少时,本来用的时间就少,而线程的调度也是需要开销的,以及其他增加的语句执行也会花费时间,所以综合起来多线程不但体现不出来优势,反而会托后退。

线程的数量也不是越多越好,大家可以试着改变程序中的N。

单核CPU

多线程:

这里写图片描述

普通程序:

这里写图片描述

在单核CPU上测试,多线程在这里毫无优势,反而因为线程的额外开销增加了运行时间,因为单核CPU上线程并不能达到真正的并行。

所有,选择多线程还需要根据具体的场景来使用。

猜你喜欢

转载自blog.csdn.net/lyh__521/article/details/50168315
今日推荐