记录一个使C/C++多线程无法加速计算的问题

提示:本文的所有代码由C语言实现,经过测试,C++的多线程操作也会遇到同样的问题。多线程库用的是pthread.h,操作系统是win10。windows下的pthread.h安装,可以参考下这篇文章:vs2017如何配置pthread环境


前言

最近因为工作需要,调研了一下C语言的多线程使用。在测试常用功能的时候遇到这么一个诡异的问题,通过结构体获取返回值的时候,多线程操作变慢了。经过一天的努力,最终解决了这个问题。以下是对该问题的记录。


一、多线程代码

1.带有返回值的多线程代码

下面代码包括生成一个5行1000万列的随机数组,然后分别使用多线程的和单线程的方法对每一行进行求和。其中多线程的参数是一个结构体,包括要求和的数组和一个sum返回值。

#include <stdio.h>
#include <time.h>
#include <pthread.h>  

//定义随机数组的行和列
#define ROW   5
#define COL 10000000

//获得随机数组
int ** getRandom()
{
	printf("生成%dX%d的随机数组\n", ROW, COL);
	int  **r;
	r = (int **)malloc(ROW * sizeof(int));
	for (int i = 0; i < ROW; i++) {
		r[i] = (int *)malloc(COL * sizeof(int));
	}
	srand((unsigned)time(NULL));
	for (int i = 0; i < ROW; i++) {
		for (int j = 0; j < COL; ++j)
		{
			r[i][j] = rand();
		}
	}
	printf("随机数组生成完毕\n\n");
	return r;
}

//定义传入线程的结构体
typedef struct TagValue
{
	int *arr;
	long long sum;
} Tag;

//子线程调用求和方法
void* threadSum(void *d) {
	Tag *v = (Tag*)d;
	int *arr = v->arr;
	for (int i = 0; i < COL; i++) {
		v->sum += *(arr + i);
	}
}

//多线程主方法
void  testThreadTime(int **r) {
	//计算多线程运行时间
	clock_t start, end;
	//传入参数结构体
	Tag res[ROW];
	//线程id号
	pthread_t ths[ROW];
	//记时开始
	start = clock();
	for (int i = 0; i < ROW; i++) {
		res[i].arr = r[i];
		res[i].sum = 0;
		//开启子线程
		int ret_thrd1 = pthread_create(&ths[i], NULL, (void *)&threadSum, (void *)&res[i]);
		// 线程创建成功,返回0,失败返回失败号
		if (ret_thrd1 != 0) {
			 printf("子线程%d创建失败\n",i);
		}else {
			printf("子线程%d创建成功\n",i);
		}
	}
	//增加join函数,使主线程等待子线程都结束
	for (int i = 0; i < ROW; i++) {
		pthread_join(ths[i], NULL);
	}
	//打印返回值
	printf("多线程的执行结果是:\n");
	for (int i = 0; i < ROW; i++) {
		printf("%lld\n", res[i].sum);
	}
	printf("主线程执行完毕\n");
	//计时结束
	end = clock();
	printf("Time Used: %f\n\n", difftime(end, start));
}

//非多线程对照方法
void  testNoThreadTime(int **r) {
	clock_t start, end;
	//int **r = getRandom();
	long long res[ROW];
	memset(res, 0, ROW * sizeof(long long));
	start = clock();
	for (int i = 0; i < ROW; i++) {
		for (int j = 0; j < COL; j++) {
			res[i] += r[i][j];
		}
	}
	end = clock();
	printf("对照组执行结果是:\n");
	for (int i = 0; i < ROW; i++) {
		printf("%lld\n", res[i]);
	}
	printf("Time Used: %f\n\n", difftime(end, start));
}


int main() {
	int **r = getRandom();
	testThreadTime(r); 
	testNoThreadTime(r);  
	getchar();
	return 0;
}

2.结果展示

多线程结果展示
可见多线程不但没有减少计算时间,反而增加了很多。

二、问题修复

1.修改子线程调用方法

出现问题是threadSum函数里的这句代码v->sum += *(arr + i),这句代码对主线程里声明的地址内容进行了大量的修改操作。按照下面方式修改,声明临时变量sum,求和在临时变量sum中进行,只需进行简单的修改,多线程变慢的问题就解决了

void* threadSum(void *d) {
	Tag *v = (Tag*)d;
	int *arr =v->arr;
	long long sum = 0;
	for (int i = 0; i < COL; i++) {
		sum+=*(arr + i);
	}
	v->sum = sum;
}

2.结果展示

在这里插入图片描述


修改之后,多线程已经可以正常提升计算效率了。

总结

在C/C++的多线程使用过程中,一定要注意在子线程中对传入地址的写操作。频繁的跨线程写操作,会带来效率的大幅降低。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值