Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/126.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 速度优化:向量队列与指向向量的指针队列_C++_Vector_Stl - Fatal编程技术网

C++ 速度优化:向量队列与指向向量的指针队列

C++ 速度优化:向量队列与指向向量的指针队列,c++,vector,stl,C++,Vector,Stl,我试图将向量(实际上是一个管理向量的对象)存储到队列中,以便以后处理它们 以下是我当前的实现: // in constructor: q = new boost::lockfree::spsc_queue<MyObject>(num_elements_in_q); // ... bool Push(const MyObject& push_me) { return q->push(push_me); } // ... // in Pop() (i.e., th

我试图将向量(实际上是一个管理向量的对象)存储到队列中,以便以后处理它们

以下是我当前的实现:

// in constructor:  
q = new boost::lockfree::spsc_queue<MyObject>(num_elements_in_q);
// ...
bool Push(const MyObject& push_me) { return q->push(push_me); }
//  ...  
// in Pop() (i.e., this is how I pop stuff off of the queue)  
MyObject temp;  
q->pop(&temp);  
//在构造函数中:
q=新的boost::lockfree::spsc_队列(num_elements_in_q);
// ...
bool-Push(const-MyObject&Push-me){return q->Push(Push-me);}
//  ...  
//在Pop()中(即,这是我从队列中弹出内容的方式)
肌体温度;
q->pop和temp;
我想知道存储指针而不是对象是否有意义。以下是新代码的外观:

// in constructor:  
q = new boost::lockfree::spsc_queue<MyObject*>(num_elements_in_q);
// ...
bool Push(const MyObject& push_me) {
  MyObject* ptr = new MyObject(push_me);
  return q->push(push_me);  
}
//  ...  
// in Pop() (i.e., this is how I pop stuff off of the queue)  
MyObject* ptr;  
q->pop(&ptr);
//  do stuff with ptr
delete ptr;
//在构造函数中:
q=新的boost::lockfree::spsc_队列(num_elements_in_q);
// ...
bool Push(常量MyObject和Push_me){
MyObject*ptr=新的MyObject(推送);
返回q->push(push_me);
}
//  ...  
//在Pop()中(即,这是我从队列中弹出内容的方式)
MyObject*ptr;
q->pop和ptr;
//用ptr做一些事情
删除ptr;
在最小化推送操作所需时间方面,哪种方法最好?一般来说,最好是存储整个MyObject还是只存储指针(并动态分配内存)?我意识到,通过存储整个MyObject,仍然需要动态内存,因为MyObject中的向量需要调整大小

我的最终目标是最大限度地减少推送所需的时间(以及从一个操作到下一个操作的任何时间抖动),而以牺牲内存使用和执行Pop()所需的时间为代价(顶级版本需要在Pop()中复制,这可以通过使用指针来避免)


谢谢你的帮助。此外,我目前无法访问此系统上的探查器,否则我可能已经有了答案。

如果不进行实际测试,我会说使用new分配内存可能比复制整个MyObject花费更多。当然,这取决于MyObject的实现方式

另一个要考虑的是,存储对象本身可能会给你一些更高的缓存命中率,假设Booo::RoCuSyFLE在连续内存中存储数据。因为您的所有对象都可以由cpu批量读取,因此一起存储在一级缓存中。使用指针将导致CPU从指针指向的内存加载内容,并可能将队列中的其他元素从缓存中踢出


当然,要100%确定你必须测量它。

同意,在几乎所有情况下,存储指针必须比存储比指针大的东西更便宜

在每种情况下,似乎都有MyObject的副本构造。通过让调用者负责对象的生命周期,有机会删除此结构:

  • 提供右值接口将允许使用移动构造,而移动构造的重量可能要轻得多,这取决于为MyObject选择的表示
  • 或者,您可以传递并排队
    std::unique_ptr
    智能指针,强制调用方显式管理对象的构造和生命周期保证

  • 如果速度是最终目标,那么可以考虑在入侵模式中使用某种类型。所谓侵入式,我的意思是,向每个对象添加链接指针,并使用这些指针构建队列。最大的优点是,将对象添加到队列时,内存分配为零。如果将所有对象分配到一个大块中(如使用向量),则对象将保持在一起。这意味着在列表中迭代将不太可能导致缓存未命中

    这确实意味着您可能需要在队列上实现自己的锁定,但请记住,正确实现的无竞争互斥体应该与用于无锁编程的原子操作一样便宜


    查看:了解模板化boost实现的详细信息

    考虑到了解正在发生的事情的唯一真正方法是测量,我使用了一种粗略的方法来计算我的执行时间(对于这两种实现都是)

    以下是在队列中运行2500次插入的结果。基于围绕函数调用的boost::timer,时间以秒为单位。注意:这些是每次通话的平均次数

    用于存储整个对象:
    运行1:0.000343423
    运行2:0.000338752
    运行3:0.000339651
    运行4:0.000320011
    运行5:0.00034017

    用于存储指针:
    运行1:0.00033717
    运行2:0.00033645
    运行3:0.000336106
    运行4:0.00033674
    运行5:0.000336841

    然后我去make并将测试增加到25000次插入,因为我想知道最初是否存在缓存未命中之类的情况。结果如下:

    用于存储整个对象:
    运行1:0.00023566
    运行2:0.000255699
    运行3:0.000250765
    运行4:0.000239108
    运行5:0.000264594

    用于存储指针:
    运行1:0.000317314
    运行2:0.000316985
    运行3:0.000414893
    运行4:0.000334542
    运行5:0.00033179


    看起来(这只是我的理论)在最初的Push()调用中,在对象中找到的向量被正确地调整了大小。从那时起,复制构造函数不再需要支付每次调整向量大小的罚款,它将成为一个更高效的过程。

    只需测量速度。衡量是对绩效做出有意义陈述的唯一方式。对事情如何运作的一点了解不会有什么坏处。。。毕竟,时间是无价的。我不知道boost数据结构是如何工作的,但对于一个常规的
    std::deque
    ,我更喜欢存储向量本身。这只是我的直觉。
    sizeof(MyObject)
    是什么?它有便宜的交换和/或移动拷贝构造/分配吗?
    同意,在几乎所有情况下,存储指针必须比存储比指针大的东西便宜。
    除了额外的内存使用,额外的数据