Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/128.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++例程。此例程的主要瓶颈是对象向量的push_back()。我试着用一个deque来代替,甚至试着用一个列表。但奇怪的是(与理论相反),deque和list实现的运行速度比向量实现慢得多_C++_Stl - Fatal编程技术网

向后推送向量、数据和列表 我试图优化C++例程。此例程的主要瓶颈是对象向量的push_back()。我试着用一个deque来代替,甚至试着用一个列表。但奇怪的是(与理论相反),deque和list实现的运行速度比向量实现慢得多

向后推送向量、数据和列表 我试图优化C++例程。此例程的主要瓶颈是对象向量的push_back()。我试着用一个deque来代替,甚至试着用一个列表。但奇怪的是(与理论相反),deque和list实现的运行速度比向量实现慢得多,c++,stl,C++,Stl,事实上,对于deque和list实现,甚至clear()的运行速度也比向量实现慢得多。在这种情况下,向量实现似乎是最快的,而列表实现是最慢的 有什么建议吗 注意:vector reserve()可以加快实现速度,但无法完成,因为它的大小未知 谢谢。您是将对象本身推回,还是指向它们的指针?指针通常会更快,因为与对象的大小相比,只需复制4-8个字节。您需要提供有关例程行为的更多信息 在一个地方,你关心的是向后推()的速度;在另一个地方,你关心的是清除()。你是在建造容器,做些什么然后把它倾倒掉吗 您

事实上,对于deque和list实现,甚至clear()的运行速度也比向量实现慢得多。在这种情况下,向量实现似乎是最快的,而列表实现是最慢的

有什么建议吗

注意:vector reserve()可以加快实现速度,但无法完成,因为它的大小未知


谢谢。

您是将对象本身推回,还是指向它们的指针?指针通常会更快,因为与对象的大小相比,只需复制4-8个字节。

您需要提供有关例程行为的更多信息

在一个地方,你关心的是
向后推()
的速度;在另一个地方,你关心的是
清除()
。你是在建造容器,做些什么然后把它倾倒掉吗


您看到的
clear()
的结果是因为
vector
只需要释放一个内存块,
deque
需要释放几个,而
列表
必须为每个元素释放一个元素。

Deque的结构比vector更复杂,两者之间的速度差异在很大程度上取决于具体的实现和被推回的元素的实际数量,但对于大量数据,它应该更快。clear()可能会慢一些,因为它可能会选择删除更复杂的底层结构。列表也是如此。

向量构建或清除速度比deque或list预期的要快;这是一个更简单的数据结构

在这方面,它必须做两件事:

  • 检查向量是否足够大,以便 保留新项目
  • 插入新项目
  • 通常可以通过简单地调整向量大小并使用设置项来消除步骤1来加快速度

    更新: 原始海报要求举例说明。 下面的代码乘以128次超级插入和输出

    push_back           : 2.04s
    reserve & push_back : 1.73s
    resize & place      : 0.48s
    
    在旧的P4机器上使用Debian/Lenny上的g++-O3编译和运行时

    #include <iostream>
    #include <time.h>
    #include <vector>
    
    int main(int,char**)
    {
      const size_t n=(128<<20);
    
      const clock_t t0=clock();
      {
        std::vector<unsigned char> a;
        for (size_t i=0;i<n;i++) a.push_back(i);
      }
      const clock_t t1=clock();
      {
        std::vector<unsigned char> a;
        a.reserve(n);
        for (size_t i=0;i<n;i++) a.push_back(i);
      }
      const clock_t t2=clock();
      {
        std::vector<unsigned char> a;
        a.resize(n);
        for (size_t i=0;i<n;i++) a[i]=i;
      }
      const clock_t t3=clock();
    
      std::cout << "push_back           : " << (t1-t0)/static_cast<float>(CLOCKS_PER_SEC) << "s" << std::endl;
      std::cout << "reserve & push_back : " << (t2-t1)/static_cast<float>(CLOCKS_PER_SEC) << "s" << std::endl;
      std::cout << "resize & place      : " << (t3-t2)/static_cast<float>(CLOCKS_PER_SEC) << "s" << std::endl;
    
      return 0;  
    }
    
    #包括
    #包括
    #包括
    int main(int,char**)
    {
    const size_t n=(128关于push_back()MSVC中使用的STL的实现速度很慢,而且没有帮助,它的工作原理是这样的:当你第一次创建一个向量时,它会为10个元素保留空间。从那时起,每当它满了,它就会为向量中的元素数目的1.5倍保留空间。所以,类似于10、15、22、33、49、73、105、157。。。重新分配是昂贵的

    即使您不知道确切的大小,reserve()也会很有用。reserve()不会在需要时阻止向量的增长。如果您保留()向量的大小超过了这个大小,你仍然可以通过保留来改进。如果向量变得更小,那么,也许这是可以的,因为在较小的尺寸下,性能通常会更好


    您需要在发布模式下进行概要分析,以确定哪种策略最有效。

    如果您不知道要添加多少对象,则很难找到最佳解决方案。您所能做的就是尽量减少您所知道的成本-在这种情况下,您的向量正在不断调整大小

    你可以通过两种方式做到这一点

    1) 将您的操作分为构建和完成。这是将列表构建到一个保证足够大的向量中,并在完成后将其复制到另一个向量中

    例如


    您可以选择一个不同的容器,该容器不会在调整大小时复制所有元素,但您的瓶颈可能会成为新元素的单个内存分配。

    如果您希望vector快速,则必须保留()足够的空间。这会产生巨大的差异,因为每次增长都非常昂贵。如果你不知道,请做出一个好的猜测。

    如果对象的复制很慢,“push_back()”可能会很慢。如果默认构造函数很快,并且你有办法使用swap避免复制,那么你的程序可能会快得多

    void test_vector1()
    {
        vector<vector<int> > vvi;
        for(size_t i=0; i<100; i++)
        {
            vector<int> vi(100000, 5);
            vvi.push_back(vi);    // copy of a large object
        }
    }
    
    void test_vector2()
    {
        vector<int> vi0;
        vector<vector<int> > vvi;
        for(size_t i=0; i<100; i++)
        {
            vector<int> vi(100000, 5);
            vvi.push_back(vi0);  // copy of a small object
            vvi.back().swap(vi); // swap is fast
        }
    }
    

    你必须根据你要用它做什么来选择你的容器

    相关操作包括:扩展(使用
    推送
    )、插入(可能根本不需要)、提取、删除

    在,每个容器类型的操作都有一个非常好的概述


    如果操作是
    push
    -bound,那么向量优于其他所有操作是有意义的。deque的优点是它分配固定的块,因此可以更有效地利用碎片内存。

    另一个注意事项:push_-back的结果类似,向量是最快的,列表是最慢的。你在尝试什么推回?复制成本高吗?它有昂贵的复制构造函数吗?发布更多详细信息。如果复制成本高,并且你有“交换”功能,你可以避免一些复制(见我的答案)确保在发布模式下配置文件。根据编译器的不同,比较Debug vector和deque几乎没有意义。这是预期的,因为vector和list的n个项的push_back是O(n),但vector的结构更简单(只是数组)因此,push_back需要执行的操作更少。但是,插入当然会不同。是的,我正在推回对象。我将尝试使用指针。谢谢。对象的数据没有被复制…调用了复制构造函数。在某些情况下,这比普通的memcpy慢。push_back()的结果类似同样,向量是最快的,列表是最慢的。我正在尝试优化的主要例程是一个有for循环(将计数为1亿或更多)的例程,其中一个对象正在运行
    if (vec.capacity() == vec.size())
      vec.reserve(vec.size() + 16);  // alloc space for 16 more objects
    
    void test_vector1()
    {
        vector<vector<int> > vvi;
        for(size_t i=0; i<100; i++)
        {
            vector<int> vi(100000, 5);
            vvi.push_back(vi);    // copy of a large object
        }
    }
    
    void test_vector2()
    {
        vector<int> vi0;
        vector<vector<int> > vvi;
        for(size_t i=0; i<100; i++)
        {
            vector<int> vi(100000, 5);
            vvi.push_back(vi0);  // copy of a small object
            vvi.back().swap(vi); // swap is fast
        }
    }
    
    VS2005-debug 
    * test_vector1 -> 297
    * test_vector2 -> 172
    
    VS2005-release
    * test_vector1 -> 203
    * test_vector2 -> 94
    
    gcc
    * test_vector1 -> 343
    * test_vector2 -> 188
    
    gcc -O2
    * test_vector1 -> 250
    * test_vector2 -> 156