C&C++   发布时间:2022-04-03  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了c – 代码运行速度比2个线程慢1倍大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。
原始问题:

所以我编写了一些代码来试验线程并进行一些测试.

代码应创建一些数字,然后找到这些数字的平均值.

我认为到目前为止,向您展示我的内容更容易.我期待两个线程的代码运行速度大约是其两倍.用秒表测量它我觉得它运行速度慢了6倍!编辑:现在使用计算机和clock()函数来告诉时间.

@H_944_8@void findmean(std::vector<double>*,std::size_t,double*); int main(int argn,char** argv) { // Program entry point std::cout << "Generating data..." << std::endl; // Create a vector containing many variables std::vector<double> data; for(uint32_t i = 1; i <= 1024 * 1024 * 128; i ++) data.push_BACk(i); // Calculate mean using 1 core double mean = 0; std::cout << "CalculaTing mean,1 Thread..." << std::endl; findmean(&data,data.size(),&mean); mean /= (doublE)data.size(); // Print result std::cout << " Mean=" << mean << std::endl; // Repeat,using two threads std::vector<std::thread> thread; std::vector<double> result; result.push_BACk(0.0); result.push_BACk(0.0); std::cout << "CalculaTing mean,2 Threads..." << std::endl; // Run threads uint32_t halfsize = data.size() / 2; uint32_t A = 0; uint32_t B,C,D; // Split the data into two blocks if(data.size() % 2 == 0) { B = C = D = halfsize; } else if(data.size() % 2 == 1) { B = C = halfsize; D = hsz + 1; } // Run with two threads thread.push_BACk(std::thread(findmean,&data,A,B,&(result[0]))); thread.push_BACk(std::thread(findmean,D,&(result[1]))); // Join threads thread[0].join(); thread[1].join(); // Calculate result mean = result[0] + result[1]; mean /= (doublE)data.size(); // Print result std::cout << " Mean=" << mean << std::endl; // Return return EXIT_succesS; } void findmean(std::vector<double>* datavec,std::size_t start,std::size_t length,double* result) { for(uint32_t i = 0; i < length; i ++) { *result += (*dataveC).at(start + i); } }

我认为这段代码并不完美,如果你能提出改进方法,那么我也会感激不尽.

注册变量:

有几个人建议为函数’findmean’创建一个局部变量.这就是我所做的:

@H_944_8@void findmean(std::vector<double>* datavec,double* result) { register double holding = *result; for(uint32_t i = 0; i < length; i ++) { holding += (*dataveC).at(start + i); } *result = holding; }

我现在可以报告:代码运行的执行时间与单个线程几乎相同.这是6倍的大改进,但肯定必须有一种方法使它几乎快两倍?

注册变量和O2优化:

我已将优化设置为’O2′ – 我将创建一个包含结果的表.

结果到目前为止:

原始代码没有优化或寄存器变量:
1个线程:4.98秒,2个线程:29.59秒

添加了寄存器变量的代码
1个线程:4.76秒,2个线程:4.76秒

使用reg变量和-O2优化:
1线程:0.43秒,2线程:0.6秒2线程现在更慢?

根据Dameon的建议,这是在两个结果变量之间放置一大块内存:
1个线程:0.42秒,2个线程:0.64秒

TAS建议使用迭代器来访问向量的内容
1个线程:0.38秒,2个线程:0.56秒

与Core i7 920(单通道内存4GB)相同:
1个线程:0.31秒,2个线程:0.56秒

与Core i7 920(双通道内存2x2GB)相同:
1个线程:0.31秒,2个线程:0.35秒

解决方法

你遇到了false sharing的坏情况.

您的内存带宽会受到瓶颈.

虚假分享

这里的问题是每个线程都在相邻的内存位置访问结果变量.它们可能落在同一个高速缓存行上,因此每次线程访问它时,它都会在核心之间反弹高速缓存行.

每个线程都在运行此循环:

@H_944_8@for(uint32_t i = 0; i < length; i ++) { *result += (*dataveC).at(start + i); }

您可以看到结果变量经常被访问(每次迭代).因此,每次迭代时,线程都在为同一个高速缓存行而战,这个高速缓存行保存两个结果值.

通常,编译器应将*结果放入寄存器,从而删除对该存储器位置的常量访问.但是,由于您从未开启过优化,因此编译器很可能仍在访问内存位置,从而在循环的每次迭代中都会产生错误共享惩罚.

内存带宽:

一旦你消除了错误的共享并摆脱了6倍的减速,你没有得到改进的原因是因为你已经超出你的内存带宽.

确定您的处理器可能是4个内核,但它们都共享相同的内存带宽.总结数组的特定任务对每次内存访问都做很少(计算)工作.单个线程已足以最大化您的内存带宽.因此,进入更多线程不太可能为您带来太多改进.

简而言之,通过抛出更多线程,你将无法以更快的速度对数组求和.

大佬总结

以上是大佬教程为你收集整理的c – 代码运行速度比2个线程慢1倍全部内容,希望文章能够帮你解决c – 代码运行速度比2个线程慢1倍所遇到的程序开发问题。

如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。