我正在尝试新的C++11线程,但我的简单测试具有糟糕的多核性能。作为一个简单的例子,这个程序将一些平方随机数相加
#包括<;iostream>;
#包括<;螺纹>;
#包括<;向量>;
#包括<;cstdlib>;
#包括<;chrono>;
#包括<;cmath>;
双加单(整数N){
双和=0;
对于(int i=0;i<;N;++i){
总和+=sqrt(1.0*rand()/rand_MAX);
}
返回和/N;
}
void add_multi(整数N、双精度和结果){
双和=0;
对于(int i=0;i<;N;++i){
总和+=sqrt(1.0*rand()/rand_MAX);
}
结果=总和/N;
}
int main(){
srand(时间(空));
int N=1000000;
//单螺纹
自动t1=std::chrono::高分辨率时钟::现在();
双结果1=加单(N);
自动t2=标准::时钟::高分辨率时钟::现在();
自动运行时间=std::chrono::duration_cast<;std::chrono::毫秒>;(t2-t1).count();
标准::cout<;<;<;time single:<;<;<;经过的时间<;<;标准::endl;
//多线程
标准::向量<;标准::线程>;th;
内螺纹数=3;
双部分_结果[]={0,0,0};
t1=标准::时钟::高分辨率时钟::现在();
对于(int i=0;i<;nr_线程;++i)
向后推(std::thread(添加多个线程,N/nr个线程,std::ref(部分结果[i]));
用于(自动和自动:第次)
a、 join();
双结果_多核=0;
for(双重结果:部分结果)
结果\u多核+=结果;
结果_多核/=nr_线程;
t2=标准::时钟::高分辨率时钟::现在();
经过的时间=std::chrono::duration_cast<;std::chrono::毫秒>;(t2-t1).count();
标准::cout<;<;“time multi:<;<;<;经过的时间<;<;标准::endl;
返回0;
}
在Linux和3core机器上使用“g++-std=c++11-pthread test.cpp”编译,典型的结果是
单曲时间:33
时间:565
因此,多线程版本要慢一个数量级以上。我使用了随机数和sqrt使示例变得不那么琐碎,并且易于进行编译器优化,所以我没有主意了
编辑:
- 这个问题会扩展到更大的N,因此问题不是短期的运行时间
- 创建线程的时间不是问题所在。排除它不会显著改变结果
哇,我发现了问题。确实是兰德()。我用C++11等价物替换了它,现在运行时可以完美地扩展。谢谢大家
在我的系统上,行为是相同的,但正如Maxim提到的,rand不是线程安全的。当我将rand改为rand_r时,多线程代码会像预期的那样更快
void add\u multi(整数N、双精度和结果){
双和=0;
无符号整数种子=时间(NULL);
对于(int i=0;i<;N;++i){
总和+=sqrt(1.0*rand_r(&;seed)/rand_MAX);
}
结果=总和/N;
}