为什么我的tbb比串行还慢?

wanglei5695312 2010-01-16 05:07:08
程序如下:

#include "stdafx.h"
#include <iostream>
#include <tbb/task_scheduler_init.h>
#include <tbb/task.h>
#include "tbb/tick_count.h"
#include <windows.h>
using namespace std;
using namespace tbb;

struct printtask :task {
printtask(int n) :m_n(n){}
task* execute() {
cout < < m_n;
return NULL;
}
private:
int m_n;
};

int main() {

//开始tbb执行
tick_count t0, t1;
t0 = tick_count::now();
task *dummy = new(task::allocate_root()) empty_task;
dummy->set_ref_count(10+1);
for(int i=0; i <10; i++) {
task* childtask = new(dummy->allocate_child()) printtask(i);
dummy->spawn(*childtask);
}
dummy->wait_for_all();
dummy->destroy(*dummy);
t1 = tick_count::now();
cout < < endl < < "tbb time: " < < (t1-t0).seconds() < < endl;


//开始串行执行
t0 = tick_count::now();
for (int i = 0; i < 10; i++) {
cout < < i;
}
cout < < endl;
t1 = tick_count::now();
cout < < "serial time: " < < (t1-t0).seconds() < < endl;
return 0;
}

运行结果如下:

9081726354
tbb time: 0.00430087
0123456789
serial time: 0.000346368

tbb消耗的时间要多于串行10倍,我不知道为什么?
...全文
874 41 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
41 条回复
切换为时间正序
请发表友善的回复…
发表回复
freeboy1015 2012-03-28
  • 打赏
  • 举报
回复
我也遇到了同样的问题,我的cpu(intel core tm 2 duo cpu E7400)明明是双核的,为什么会只有一个cpu在跑?[Quote=引用 37 楼 assassin5616 的回复:]

我们的程序是一样的,我也是一直用的四核,不过加速比这事不是简单地成倍数关系的,就好像从10亿次到100亿次的时候提升超级明显,这应该跟多余的循环是在子函数里有关,不过这复杂了点,需要对tbb的原理非常清楚了。
我的tbb也是2.2的,不过我们的平台不一样,我是linux,你是windows。我在我的机器上也看了一下,跑tbb的时候每个cpu也都在跑,占用大概在30%左右,而当串行跑的时候,很明……
[/Quote]
freeboy1015 2012-03-28
  • 打赏
  • 举报
回复
为什么会只有一个cpu在跑,我也遇到了同样的问题,我用的是parallel_do,明明我的cpu是双核的啊(intel core tm 2 duo cpu E7400)[Quote=引用 37 楼 assassin5616 的回复:]

我们的程序是一样的,我也是一直用的四核,不过加速比这事不是简单地成倍数关系的,就好像从10亿次到100亿次的时候提升超级明显,这应该跟多余的循环是在子函数里有关,不过这复杂了点,需要对tbb的原理非常清楚了。
我的tbb也是2.2的,不过我们的平台不一样,我是linux,你是windows。我在我的机器上也看了一下,跑tbb的时候每个cpu也都在跑,占用大概在30%左右,而当串行跑的时候,很明……
[/Quote]
wanglei5695312 2010-01-20
  • 打赏
  • 举报
回复
嗯,我加了,不过没变啊,结果
tbb time: 1.05429
serial time: 0.379389
assassin5616 2010-01-20
  • 打赏
  • 举报
回复
一个比较不靠谱的建议,在 blocked_range <int>& range 的前面加上const试一下,这个东西跟优化有关。不过我在我的机器上试了一下,结果是一样的。
assassin5616 2010-01-20
  • 打赏
  • 举报
回复
我们的程序是一样的,我也是一直用的四核,不过加速比这事不是简单地成倍数关系的,就好像从10亿次到100亿次的时候提升超级明显,这应该跟多余的循环是在子函数里有关,不过这复杂了点,需要对tbb的原理非常清楚了。
我的tbb也是2.2的,不过我们的平台不一样,我是linux,你是windows。我在我的机器上也看了一下,跑tbb的时候每个cpu也都在跑,占用大概在30%左右,而当串行跑的时候,很明显只有一个cpu的占用率达到100%。如果你也是这种情况,但是tbb却还是比串行慢,我就没招了,技穷与此乐
wanglei5695312 2010-01-20
  • 打赏
  • 举报
回复
assassin5616:
你还是四核吗?你的加速比分别是:2.895 5.59 1.7 第二个是不是超过4了
wanglei5695312 2010-01-20
  • 打赏
  • 举报
回复
[Quote=引用 33 楼 assassin5616 的回复:]
引用 31 楼 wanglei5695312 的回复:
引用 30 楼 assassin5616 的回复:
引用 27 楼 wanglei5695312 的回复:
引用 26 楼 assassin5616 的回复:
引用 22 楼 wanglei5695312 的回复:
引用 18 楼 assassin5616 的回复:
楼主好好看看tbb的文档吧,简单说一下,tbb的下面也是用线程的,你就10个循环,居然spwan出10个线程出来,能快得了吗。而且tbb能快的一个决定因素就是多核的出现,你电脑有几个核?就敢spwan这么多次。
建议就是,第一个,把循环个数提高到千万级别,甚至更高,用tbb里面的循环,顶多拆分两次就好了,再跟串行速度比。
当然,如果你是单核的cpu,那是白搭,用tbb还不如不用。


spawn不是启动线程的意思,是放入线程池,我机子是双核,默认启动两个线程,这个和循环个数没有关系,我试过了

当然不是每次spawn都会产生一个新线程了,但是你最开始调的时候要不要?后来加入的时候要不要判断是否要产生新线程,这些都是要花时间的吧,光是这些时间都比你串行跑十次循环多了。

还有这个cout,IO输出是不建议并发的,因为最后到IO这里还是要到同一条线上,只会更慢。

建议你可以做个很简单的实验,使用一下parallel_for,只做空循环。你会发现循环数目很小时,paralle_for更慢,因为创建线程这些花费的时间占主导,如果循环数目到千万级别,你就会发现parallel_for 更快了。 你要是把cout加上,parallel_for马上变得更慢,而且循环数越大,parallel_for越慢,这就是因为前面IO的原因。你要是在每个cout后面加上endl,循环数很大的时候,parallel_for就慢得吓死你了。


我让n=100000000

class Parallel_A {
public:
void operator()(blocked_range <int>& range) const {
for (int i = range.begin(); i != range.end(); i++) {
}
}
};
空循环,试验结果:
tbb time: 1.08414
serial time: 0.385835
我让n=1000000000(比上面多一个0)
试验结果:
tbb time: 10.4568
serial time: 3.85928
再多一个0,死循环了,没结果了
目前还是tbb时间大于serial


在你的机器上是这样的话,比较合理的解释就是你的双核实际只有一个核在跑,而tbb起了多个线程,这样在一个核上用多线程跑空循环时间几乎是跟线程的个数成倍数增加的。因为从你的数据可以看出来,跑1千万次循环和跑一亿次循环的时候不管是tbb还是单线程时间都是等比例增加的(不过循环更小的时候时间增加不是等比的,tbb和单线程都不是)。
我下午的时候在AMD四核8片的机器上跑,一千万次空循环单线程差不多是0.03秒,而tbb是0.01秒。数据可能不准确,明天把准确的数据贴上来。反正就是循环超过1千万次后,tbb就要快多了。


好吧,那谢谢了

我刚才在intel xeon 四核上运行了
n=100000000 运行结果:
tbb time: 0.970799
serial time: 0.351196
n=1000000000 运行结果
tbb time: 9.55959
serial time: 3.51396
我注意了四个核的变化,四个核都运行了,明天你在你机子上再运行一下

今天早上我又运行了一次,下面是我的结果。如果你的结果一直这样,我就真的不明白了,要不你把所有code贴出来,不过不太可能是code的问题,毕竟是很简单的code.
循环一千万次的时候:
tbb time : 0.008739
serial time : 0.0253
循环一亿次的时候。
tbb time : 0.036325
serial time : 0.203049
循环十亿次的时候
tbb time : 0.43934
serial time : 0.748951
循环一百亿次的时候(因为已经超过整数的最大值,所以在空循环里增加了一个子函数空循环10次)
tbb time : 1.52934
serial time : 10.1164


[/Quote]

下面是我的代码,你看对吗,你的tbb版本是多少?我是2.2
// 9.cpp : 定义控制台应用程序的入口点。
#include "stdafx.h"
#include "tbb/task_scheduler_init.h"
#include "tbb/blocked_range.h"
#include "tbb/parallel_for.h"
#include "tbb/spin_mutex.h"
#include "tbb/tick_count.h"
#include "tbb/atomic.h"
#include <iostream>
#include <windows.h>
#define n 10000000
using namespace std;
using namespace tbb;

class Parallel_A {
public:
void operator()(blocked_range<int>& range) const {
for (size_t i = range.begin(); i != range.end(); i++) {
}
}
};

void parallela() {
parallel_for(blocked_range<int>(0, n), Parallel_A(), auto_partitioner());
}

int _tmain(int argc, _TCHAR* argv[]) {
tick_count t0 = tick_count::now();
parallela();
tick_count t1 = tick_count::now();
cout << "tbb time: " << (t1-t0).seconds() << endl;
tick_count t2 = tick_count::now();
for (size_t i = 0; i < n; i++) {
}
tick_count t3 = tick_count::now();
cout << "serial time: " << (t3-t2).seconds() << endl;
return 0;
}
wanglei5695312 2010-01-20
  • 打赏
  • 举报
回复
今天早上我又运行了一次,下面是我的结果。如果你的结果一直这样,我就真的不明白了,要不你把所有code贴出来,不过不太可能是code的问题,毕竟是很简单的code.
循环一千万次的时候:
tbb time : 0.008739
serial time : 0.0253
循环一亿次的时候。
tbb time : 0.036325
serial time : 0.203049
循环十亿次的时候
tbb time : 0.43934
serial time : 0.748951
循环一百亿次的时候(因为已经超过整数的最大值,所以在空循环里增加了一个子函数空循环10次)
tbb time : 1.52934
serial time : 10.1164
[/Quote]


下面是我的代码,你看对吗,你的tbb版本是多少?我是2.2
// 9.cpp : 定义控制台应用程序的入口点。
#include "stdafx.h"
#include "tbb/task_scheduler_init.h"
#include "tbb/blocked_range.h"
#include "tbb/parallel_for.h"
#include "tbb/spin_mutex.h"
#include "tbb/tick_count.h"
#include "tbb/atomic.h"
#include <iostream>
#include <windows.h>
#define n 10000000
using namespace std;
using namespace tbb;

class Parallel_A {
public:
void operator()(blocked_range<int>& range) const {
for (size_t i = range.begin(); i != range.end(); i++) {
}
}
};

void parallela() {
parallel_for(blocked_range<int>(0, n), Parallel_A(), auto_partitioner());
}

int _tmain(int argc, _TCHAR* argv[]) {
tick_count t0 = tick_count::now();
parallela();
tick_count t1 = tick_count::now();
cout << "tbb time: " << (t1-t0).seconds() << endl;
tick_count t2 = tick_count::now();
for (size_t i = 0; i < n; i++) {
}
tick_count t3 = tick_count::now();
cout << "serial time: " << (t3-t2).seconds() << endl;
return 0;
}
assassin5616 2010-01-20
  • 打赏
  • 举报
回复
[Quote=引用 31 楼 wanglei5695312 的回复:]
引用 30 楼 assassin5616 的回复:
引用 27 楼 wanglei5695312 的回复:
引用 26 楼 assassin5616 的回复:
引用 22 楼 wanglei5695312 的回复:
引用 18 楼 assassin5616 的回复:
楼主好好看看tbb的文档吧,简单说一下,tbb的下面也是用线程的,你就10个循环,居然spwan出10个线程出来,能快得了吗。而且tbb能快的一个决定因素就是多核的出现,你电脑有几个核?就敢spwan这么多次。
建议就是,第一个,把循环个数提高到千万级别,甚至更高,用tbb里面的循环,顶多拆分两次就好了,再跟串行速度比。
当然,如果你是单核的cpu,那是白搭,用tbb还不如不用。


spawn不是启动线程的意思,是放入线程池,我机子是双核,默认启动两个线程,这个和循环个数没有关系,我试过了

当然不是每次spawn都会产生一个新线程了,但是你最开始调的时候要不要?后来加入的时候要不要判断是否要产生新线程,这些都是要花时间的吧,光是这些时间都比你串行跑十次循环多了。

还有这个cout,IO输出是不建议并发的,因为最后到IO这里还是要到同一条线上,只会更慢。

建议你可以做个很简单的实验,使用一下parallel_for,只做空循环。你会发现循环数目很小时,paralle_for更慢,因为创建线程这些花费的时间占主导,如果循环数目到千万级别,你就会发现parallel_for 更快了。 你要是把cout加上,parallel_for马上变得更慢,而且循环数越大,parallel_for越慢,这就是因为前面IO的原因。你要是在每个cout后面加上endl,循环数很大的时候,parallel_for就慢得吓死你了。


我让n=100000000

class Parallel_A {
public:
void operator()(blocked_range <int>& range) const {
for (int i = range.begin(); i != range.end(); i++) {
}
}
};
空循环,试验结果:
tbb time: 1.08414
serial time: 0.385835
我让n=1000000000(比上面多一个0)
试验结果:
tbb time: 10.4568
serial time: 3.85928
再多一个0,死循环了,没结果了
目前还是tbb时间大于serial


在你的机器上是这样的话,比较合理的解释就是你的双核实际只有一个核在跑,而tbb起了多个线程,这样在一个核上用多线程跑空循环时间几乎是跟线程的个数成倍数增加的。因为从你的数据可以看出来,跑1千万次循环和跑一亿次循环的时候不管是tbb还是单线程时间都是等比例增加的(不过循环更小的时候时间增加不是等比的,tbb和单线程都不是)。
我下午的时候在AMD四核8片的机器上跑,一千万次空循环单线程差不多是0.03秒,而tbb是0.01秒。数据可能不准确,明天把准确的数据贴上来。反正就是循环超过1千万次后,tbb就要快多了。


好吧,那谢谢了

我刚才在intel xeon 四核上运行了
n=100000000 运行结果:
tbb time: 0.970799
serial time: 0.351196
n=1000000000 运行结果
tbb time: 9.55959
serial time: 3.51396
我注意了四个核的变化,四个核都运行了,明天你在你机子上再运行一下
[/Quote]
今天早上我又运行了一次,下面是我的结果。如果你的结果一直这样,我就真的不明白了,要不你把所有code贴出来,不过不太可能是code的问题,毕竟是很简单的code.
循环一千万次的时候:
tbb time : 0.008739
serial time : 0.0253
循环一亿次的时候。
tbb time : 0.036325
serial time : 0.203049
循环十亿次的时候
tbb time : 0.43934
serial time : 0.748951
循环一百亿次的时候(因为已经超过整数的最大值,所以在空循环里增加了一个子函数空循环10次)
tbb time : 1.52934
serial time : 10.1164

suanyuan 2010-01-20
  • 打赏
  • 举报
回复
[Quote=引用 18 楼 assassin5616 的回复:]
楼主好好看看tbb的文档吧,简单说一下,tbb的下面也是用线程的,你就10个循环,居然spwan出10个线程出来,能快得了吗。而且tbb能快的一个决定因素就是多核的出现,你电脑有几个核?就敢spwan这么多次。
建议就是,第一个,把循环个数提高到千万级别,甚至更高,用tbb里面的循环,顶多拆分两次就好了,再跟串行速度比。
当然,如果你是单核的cpu,那是白搭,用tbb还不如不用。
[/Quote]

高明。
wanghui2008se 2010-01-19
  • 打赏
  • 举报
回复
都玩并行了,厉害啊
zj_action 2010-01-19
  • 打赏
  • 举报
回复
顶。。。。
goyumeka520 2010-01-19
  • 打赏
  • 举报
回复
不~~~~~~~~~~~~~
wanglei5695312 2010-01-19
  • 打赏
  • 举报
回复
[Quote=引用 18 楼 assassin5616 的回复:]
楼主好好看看tbb的文档吧,简单说一下,tbb的下面也是用线程的,你就10个循环,居然spwan出10个线程出来,能快得了吗。而且tbb能快的一个决定因素就是多核的出现,你电脑有几个核?就敢spwan这么多次。
建议就是,第一个,把循环个数提高到千万级别,甚至更高,用tbb里面的循环,顶多拆分两次就好了,再跟串行速度比。
当然,如果你是单核的cpu,那是白搭,用tbb还不如不用。
[/Quote]

spawn不是启动线程的意思,是放入线程池,我机子是双核,默认启动两个线程,这个和循环个数没有关系,我试过了
wanglei5695312 2010-01-19
  • 打赏
  • 举报
回复
[Quote=引用 16 楼 iisbsd 的回复:]
任务太简单,因而产生多任务的额外工作成为了负担。

如果你不是执行cout < < n这种任务,而是一个耗时几秒钟的任务,你就可以看出来并发快很多了(不要出现锁资源的情况)。
[/Quote]

对,你说的基本正确,如果我把cout << 改成 sleep(1000),可以看出tbb是串行的2倍,我机子是双核,加了sleep(1000),基本上就是延迟串行时间,如果通过这样才能体现tbb优势,这有什么意义呢,tbb怎么样才能不改变串行代码时才能体现它的优势呢?
yy916 2010-01-19
  • 打赏
  • 举报
回复
顺便学习
bcl258586301 2010-01-19
  • 打赏
  • 举报
回复
学习
assassin5616 2010-01-19
  • 打赏
  • 举报
回复
楼主好好看看tbb的文档吧,简单说一下,tbb的下面也是用线程的,你就10个循环,居然spwan出10个线程出来,能快得了吗。而且tbb能快的一个决定因素就是多核的出现,你电脑有几个核?就敢spwan这么多次。
建议就是,第一个,把循环个数提高到千万级别,甚至更高,用tbb里面的循环,顶多拆分两次就好了,再跟串行速度比。
当然,如果你是单核的cpu,那是白搭,用tbb还不如不用。
流水小筑 2010-01-19
  • 打赏
  • 举报
回复
好文章,顶^^
iisbsd 2010-01-19
  • 打赏
  • 举报
回复
任务太简单,因而产生多任务的额外工作成为了负担。

如果你不是执行cout << n这种任务,而是一个耗时几秒钟的任务,你就可以看出来并发快很多了(不要出现锁资源的情况)。
加载更多回复(21)

567

社区成员

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

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