通过引用向量传递的线程函数启动缓慢
Posted
技术标签:
【中文标题】通过引用向量传递的线程函数启动缓慢【英文标题】:Thread function with passed by reference vector is slow to start 【发布时间】:2011-11-28 11:46:31 【问题描述】:我一直在查看 C++0x 线程并拥有以下代码:
#include <vector>
#include <iostream>
#include <thread>
void TestFunc(const vector<int>& vVec)
cout << "in"<<endl;
int main()
int sizer = 400000000;
vector<int> vTest(sizer);
for(int f=0; f<sizer; f++)
vTest[f] = f;
cout << "V created." << endl;
thread one(TestFunc, vTest);
one.join();
如您所见,它只是将向量传递给线程。 我不明白的是,出现“V created”消息后有一个暂停。最初这个(我假设)是被复制以在函数中使用的向量。 为了阻止这种情况,我改为通过引用传递,但这没有任何区别。
延迟似乎与向量的大小成正比,这表明它仍在复制(或对数组做某事)。 如果我在没有线程的情况下尝试相同的实验并直接调用函数,则在按值传递时会出现延迟,但在按预期传递时不会出现延迟。
我尝试使用 Boost 线程而不是 C++0x 进行相同的操作(尽管我已经读过它们大致相同)并得到了相同的结果。
这种行为是有原因的,还是我错过了一些非常明显的东西? 谢谢。
抱歉,发布了错误的测试代码。已更正。 编辑:按要求添加包括。
编译: g++44 -std=c++0x -lpthread tester.cpp -o test ...因为我在不支持 C++11 的 Linux (CentOS) 附带的标准 GNU 编译器旁边安装了 GNU 4.4。
【问题讨论】:
TestFunc 最昂贵的部分是跟踪,而不是传递的参数。看来C++0x不支持创建线程 @Mahesh:在什么系统上?这只有 4 亿个,可以轻松放入 32 位 int 中。 @BruceAdi:在 C++11 中,线程是由标准规定的,至少 gcc-4.6 确实支持它们,而且它们可以工作——我每天都在使用它们。 @BruceAdi:如果您使用的是g++
,您是否使用-pthread
选项进行编译?
而且,在这种情况下,使用endl
是完全正确的做法。 :-)
【参考方案1】:
我只是推测,因为您尚未发布使用线程的代码版本,但我怀疑您的问题是,默认情况下,std::bind
(或boost::bind
)会复制所有你绑定的参数。为避免这种情况,您可以使用std::ref
或std::cref
。
为了具体说明,您可能会像这样使用bind
:
std::bind(TestFunc, vTest)
相反,您应该像这样使用它:
std::bind(TestFunc, std::cref(vTest));
【讨论】:
这对我来说似乎有点笨拙。bind
是否无法判断该函数需要引用并存储引用?
+1 我刚刚用你的代码测试了它,你是对的。当使用 std::cref 时,延迟消失。很好发现。
@Omnifarious:我不确定这是否是可取的。闭包的预期行为(本质上是bind
的行为)是,只要闭包存在,作为参数传入的对象就会“存活”。如果bind
仅存储引用类型的所有参数的引用,则不会出现这种情况。或者,换一种方式来看:复制所有参数是一种安全的默认行为。传递引用具有一定的危险,因此应明确要求;此外,明确的ref
或cref
是以后进行维护的任何人的明确标志。
使用了 ref 并且有效。我这样使用它:线程一(TestFunc,ref(vTest));因此,就线程而言,除非您使用 ref(),否则默认情况下似乎会复制变量。我现在正在查找 ref()。
@Columbo:是的,默认情况下会复制参数。 std::thread
在这方面与std::bind
具有相同的语义。【参考方案2】:
这里的线程在哪里?看起来for
循环导致了您所指的 延迟。这里没有什么不寻常的 - 因为您正在分配一个大小为 200000000 的向量。
【讨论】:
-1:如果在看到“V created”之间没有延迟,这将是一个很好的答案。和“在”。以上是关于通过引用向量传递的线程函数启动缓慢的主要内容,如果未能解决你的问题,请参考以下文章