微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

pthreads的性能差异

我正在编写性能敏感的代码。 我实现了一个简单的调度程序来分配工作负载,主线程负责调度程序。

cpu_set_t cpus; pthread_attr_t attr; pthread_attr_init(&attr); for(int i_group =0; i_group<n_groups; i_group++){ std::cout << i_t<< "t"<<i_group << "th group of cpu" <<std::endl; for(int i =index ; i < index+group_size[i_group]; i++){ struct timeval start,end; double spent_time; gettimeofday(&start,NULL); arguments[i].i_t=i_t; arguments[i].F_x=F_xs[i_t]; arguments[i].F_y=F_ys[i_t]; arguments[i].F_z=F_zs[i_t]; cpu_ZERO(&cpus); cpu_SET(arguments[i].thread_id,&cpus); int err= pthread_attr_setaffinity_np(&attr,sizeof(cpu_set_t),&cpus); if(err!=0){ std::cout << err <<std::endl; exit(-1); } arguments[i].i_t=i_t; pthread_create( &threads[i],&attr,&cpu_work,&arguments[i]); gettimeofday(&end,NULL); spent_time = ((end.tv_sec - start.tv_sec) * 1000000u + end.tv_usec - start.tv_usec) / 1.e6; std::cout <<"create: " << spent_time << "s " << std::endl; } i_t++; cpu_count++; arr_finish[i_group]=false; } }

像上面的主线程创build。 为简单的解释,我会假设i_group = 1。 孩子的线程划分和征服了一堆matrixmatrix乘法。 这里rank是指thread_id。

int local_first = size[2]*( rank -1 )/n_compute_thread ; int local_end = size[2] * rank/n_compute_thread-1; //mkl_set_num_threads_local(10); gettimeofday(&start,NULL); for(int i_z=local_first; i_z<=local_end; i_z++ ){ cblas_dgemm( CblasColMajor,CblasNoTrans,size[0],size[1],1.0,F_x,rho[i_z],0.0,T_gamma[i_z],size[1] ); } for(int i_z=local_first; i_z<=local_end; i_z++ ){ cblas_dgemm( CblasColMajor,F_y,T_gamma2[i_z],size[0] ); } gettimeofday(&end,NULL); std::cout <<i_t <<"t"<< arg->thread_id <<"t"<< sched_getcpu()<< "t" << "compute: " <<spent_time << "s" <<std::endl;

即使工作负载公平分配,每个线程的性能差别也很大。 看到下面的结果

5 65 4 4计算:0.270229s

未定义的参考`GlewInit' – OpenGL

在相同的system()调用中连接两个命令

VBA 64位Excel不传递指向DLL函数的指针(C ++)

什么是C ++的资源?

在C#中打开/ SaveFileDialog中的应用程序链接项目

5 64 1 1计算:0.284958s

5 65 2 2计算:0.741197s

5 65 3 3计算:0.76302s

第二列显示在特定线程中完成了多lessmatrix – matrix乘法。 最后一栏显示消耗的时间。 当我首先看到这个结果的时候,我认为它和线程的亲和性有关。 因此,我添加了几行来控制线程的绑定。 但是,并没有改变最后一栏的趋势。

我的电脑有20个物理核心和20个虚拟核心。 我只做了4个子线程来testing。 当然,它是在一台Linux机器上testing的。

为什么线程的性能变化如此之大? 和如何解决它?

如何查找给定的地址是堆栈还是堆栈

如何将命名pipe道stream转换为套接字stream? (在Windows上的C ++)

如何检查系统()的最后一次调用的成功执行

哪个configuration更快? malloc vs局部variables

在Windows 7上通过QTcpsocketstream式传输图像

首先,你是否真的创建了一个调度程序? 您的代码示例建议您使用Linux调度程序,并设置线程属性对象和线程相关性参数等。这种区别与选择如何解决问题相关。

无论如何,这个问题是很大的,还有几个问题/主题可以提出来帮助澄清条件,并且接近真正的答案。 开始,这里有一些事情要考虑:

1 – 基准测试的长度。 线程池内的线程性能的次级评估似乎是不够的。 延长评估时间以使调度程序的时间得以解决。 也许几分钟。

(有关现有基准测试实用程序中使用的典型持续时间的示例, 请阅读此部分

2 – 线程优先级。 你的线程不是唯一的。 内核调度程序是否有可能定期将基准线作为属于其他进程的线程(不是您创建的进程)具有更高的优先级? (因此正在取代你的,导致任务完成时间偏差)

3 – 任务的大小。 完成每个任务所需的操作数量是否足够小以适应调度程序分配的时间片? 这可能会导致线程对线程性能问题的感知,特别是如果每​​个任务之间的操作数量有任何差异。 ( 超过分配的cpu时间片的进程会自动下移到较低的“层”,而进行I / O请求或块的进程将被移动到更高的“层”。

4 – 平等的任务 – 你提到分而治之一堆矩阵矩阵乘法 。 但是这些矩阵的大小和内容是否相同? 即你确定每个任务的操作次数是否等于所有其他任务的操作次数? 由调度器分配给每个同等优先级的线程的时间片将确保随着时间的推移,具有大于该时间片的操作数的任务可以在单个时间片中完成,这将更容易延长完成时间(由于更高的优先级的其他操作系统进程)比那些没有足够的操作,以在一个时间片内适应舒适。

5 – 其他过程。 我已经在上面的其他项目中提到过这个,但是它应该有自己的编号。 为了使用多个内核 ,同时需要多个线程。 但相反的是不正确的。 单个核心不限于单个线程。 操作系统可以随时以较高的优先级过程(在不中断任何其他内核的情况下)预先中断某个进程(线程)的一个进程(线程),从而可能使时间测量偏差。 同样,较长的基准测试时间将有助于减少由此特定现象引起的线程对线程差异的影响。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。

相关推荐