如下代码为什么在4线程下性能和2线程几乎一样?

MagiSu 2011-11-16 03:17:45
我用的是Intel i5的CPU,下面的代码没有线程通信,单线程大约1sec完成,2线程0.6秒左右完成,增加更多的线程无法让代码速度得到提升。我认为是内存的瓶颈作用。如何克服之? 谢谢指教!
#include <sys/time.h>
#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>

#define NUM_DATA 50000000
#define THREADS 1
#define BLOCK_LEN NUM_DATA/THREADS

double* data,*data1;

void* work_thread(void* pindex)
{
int index=*reinterpret_cast<int*>(pindex);
for(int j=0;j<5;++j)
{
for(int i=index;i<index+BLOCK_LEN;++i)
data1[i]=1.0/data[i];
data[j]+=0.01;
}
}

void work(void)
{
pthread_t ntid[THREADS];
void* pret;
int index[]={
0,
0+BLOCK_LEN,
0+2*BLOCK_LEN,
0+3*BLOCK_LEN
};
// create threads
for(int i=0;i<THREADS;++i)
{
int error;
error=pthread_create(&ntid[i],NULL,work_thread,&index[i]);
if (error!=0)
{
fprintf(stderr,"Fail to create thread %d\n",i);
exit(0);
}
}
for(int i=0;i<THREADS;++i)
pthread_join(ntid[i],&pret);
}

int main(void)
{
data=(double*) malloc(sizeof(double)*NUM_DATA);
data1=(double*) malloc(sizeof(double)*NUM_DATA);

if (data==NULL)
exit(1);

for(int i=0;i<NUM_DATA;++i)
data[i]=i+0.5;

struct timeval start, end;

gettimeofday(&start, NULL);

work();

gettimeofday(&end, NULL);
printf("%ld\n", ((end.tv_sec * 1000000 + end.tv_usec)
- (start.tv_sec * 1000000 + start.tv_usec)));

double value(0.0);
for(int i=0;i<NUM_DATA;++i)
{
value+=data1[i];
}

printf("%f\n",value);
}
...全文
283 9 打赏 收藏 转发到动态 举报
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
MatrixLife 2012-01-05
  • 打赏
  • 举报
回复
  i5是双核带超线程,在Windows里显示的是4核,但是真正可以互不相干并行的只能两个线程。超线程还没达到接近2倍的并行性能。
  创建线程的开销不如想象中的小。最好一次性创建出来或者用线程池。
  放到多核系统里没有加速的主要原因是没有设置“核心亲近度”,各个线程还是有竞争多个核心的现象,混乱之下反而不会很快。设置核心亲近度用"SetThreadAffinity",每个线程分配到一个单独的核心上。然后线程里的代码尽量无关联,N核系统的并行加速可以接近N倍。这个N是硬核心数,而不是带超线程的。
  这个希望有帮助:http://blog.csdn.net/lv_ximing/article/details/7093566,我还没见过 48 Cores 的系统能加速到多少,你可以按这方法测一下。
Intel_CG 2011-11-24
  • 打赏
  • 举报
回复
1.
void* work_thread(void* pindex)
{...
data[j]+=0.01; //有data race, 数据竞争访问错误。
...}

2. 用Vtune Amplifier检测LOAD_BLOCK.OVERLAP_STORE事件,如果该值过高,需改程序,使各线程访问数据的首地址相差非4K的整数倍。(The load and store have the same offset relative to the beginning of different 4K pages. This case is also called 4 K aliasing. )
MagiSu 2011-11-18
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 superdullwolf 的回复:]

开辟线程是耗费代价的,你要做的事情一定要远比开一个线程的时间要长,才值得。

比如,为了演示你的狗训练有素,你放三条狗,同时去花10分钟左右抓耗子值得。
但是,只为了他走2步,就回来,松狗,收狗的时间,比依次牵着狗走2步还麻烦。

依次牵着狗是单线程。
松开狗是多线程。
[/Quote]

我的代码里开线程消耗的时间基本上可以忽略吧。VTune上看来是可以忽略的。
超级大笨狼 2011-11-17
  • 打赏
  • 举报
回复
开辟线程是耗费代价的,你要做的事情一定要远比开一个线程的时间要长,才值得。

比如,为了演示你的狗训练有素,你放三条狗,同时去花10分钟左右抓耗子值得。
但是,只为了他走2步,就回来,松狗,收狗的时间,比依次牵着狗走2步还麻烦。

依次牵着狗是单线程。
松开狗是多线程。
MagiSu 2011-11-17
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 lvyinghong 的回复:]

你的i5才是两个核而已,不知道在真正的4核cpu上是什么表现
[/Quote]

i5有双核和四核两种,我用的是4核的。

另外我转到服务器上的48核系统里,同样也是两核最快。
MagiSu 2011-11-17
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 wxj505382 的回复:]

double* data,*data1,你针对一个集合操作,你试一下多个不同的集合,而且要针对稍大的数据量,从处理业务来说,处理量太小,都消耗到波动的堆椎里了。
[/Quote]
能解释一下么?
洞凡都都 2011-11-16
  • 打赏
  • 举报
回复
double* data,*data1,你针对一个集合操作,你试一下多个不同的集合,而且要针对稍大的数据量,从处理业务来说,处理量太小,都消耗到波动的堆椎里了。
lvyinghong 2011-11-16
  • 打赏
  • 举报
回复
你的i5才是两个核而已,不知道在真正的4核cpu上是什么表现

566

社区成员

发帖
与我相关
我的任务
社区描述
英特尔® 边缘计算,聚焦于边缘计算、AI、IoT等领域,为开发者提供丰富的开发资源、创新技术、解决方案与行业活动。
社区管理员
  • 英特尔技术社区
  • shere_lin
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧