将std :: vector <int>的每个值重置为0的最快方法

Mat*_*ler 182 c++ reset stdvector

将a的每个值重置std::vector<int>为0并保持向量初始大小的最快方法是什么?

带[]运算符的for循环?

Cat*_*lus 303

std::fill(v.begin(), v.end(), 0);
Run Code Online (Sandbox Code Playgroud)

  • 查看汇编输出,gcc实际上将此循环展开为使用m​​mx寄存器一次转储16个字节,直到它接近结束.我会说这很快.memset版本跳转到memset,我猜测它的速度一样快.我会用你的方法. (41认同)
  • 这并不完全是 OP 所要求的,而是简单地将您的向量重新分配给一个相同大小的新向量 (`v = std::vector&lt;int&gt;(vec_size,0)`) 在我的机器上似乎比 `fill` 稍快 (2认同)

Fab*_*ssi 144

一如既往,当你问最快:措施!使用上述方法(在使用Clang的Mac上):

Method      |  executable size  |  Time Taken (in sec) |
            |  -O0    |  -O3    |  -O0      |  -O3     |  
------------|---------|---------|-----------|----------|
1. memset   | 17 kB   | 8.6 kB  | 0.125     | 0.124    |
2. fill     | 19 kB   | 8.6 kB  | 13.4      | 0.124    |
3. manual   | 19 kB   | 8.6 kB  | 14.5      | 0.124    |
4. assign   | 24 kB   | 9.0 kB  | 1.9       | 0.591    |
Run Code Online (Sandbox Code Playgroud)

在10000 int的向量上使用100000次迭代.

编辑:如果更改这些数字可能会改变结果时间,您可以有一些信心(不如检查最终汇编代码),人工基准测试尚未完全优化.当然最好在真实条件下弄乱性能. 结束编辑

供参考使用的代码:

#include <vector>

#define TEST_METHOD 1
const size_t TEST_ITERATIONS = 100000;
const size_t TEST_ARRAY_SIZE = 10000;

int main(int argc, char** argv) {

   std::vector<int> v(TEST_ARRAY_SIZE, 0);

   for(size_t i = 0; i < TEST_ITERATIONS; ++i) {
   #if TEST_METHOD == 1 
      memset(&v[0], 0, v.size() * sizeof v[0]);
   #elif TEST_METHOD == 2
      std::fill(v.begin(), v.end(), 0);
   #elif TEST_METHOD == 3
      for (std::vector<int>::iterator it=v.begin(), end=v.end(); it!=end; ++it) {
         *it = 0;
      }
   #elif TEST_METHOD == 4
      v.assign(v.size(),0);
   #endif
   }

   return EXIT_SUCCESS;
}
Run Code Online (Sandbox Code Playgroud)

结论:使用std::fill(因为,正如其他人所说的最惯用)!

  • **更新**使用[Nonius](https://github.com/rmartinho/nonius)进行基准测试:[clang3.6-libc ++ - c ++ 1y-O3](http://tinyurl.com/qgvdmfe) ,[gcc4.9-c ++ 1y-O3](http://tinyurl.com/ps2u9kn)和[gcc5-c ++ 1y-O3](http://tinyurl.com/naud8xl) - **TL ; DR**:`assign`比较慢,除了`libc ++`上的小容量.代码[coliru](http://tinyurl.com/pjsonf3)/ [paste](http://tinyurl.com/npzel7t) (4认同)
  • @KyleStrand:填充不是很糟糕,它是一个模板,代码是在翻译单元中使用-O0生成的.使用memset时,您使用的是使用-O3编译的libc代码(即使使用-O0编译代码时也是如此).如果您关心调试速度并且使用模板,则必须在使用-O3编译的单独文件中使用显式模板实例化 (4认同)
  • "...没有决定性......"IMO本身的这种不确定性已经成为做基准测试的一个好点,因此优化器通常已经为OP所提出的那种情况做了很好的工作.我会将你的最后一句修改为"如果没有**显着的**性能差异......" (3认同)
  • +1.这个特定的基准测试并不是决定性的,但重点是绝对正确的,你应该编写替代品的性能测试,因为它们实际上会被使用.如果没有性能差异,那么使用最简单的来源. (2认同)
  • 另外,哇,如果你关心没有优化的速度(如果你在'调试'模式下部署,这可能是合理的,有些团队会这样做),`fill`看起来很糟糕.在这个测试中,它慢了两个数量级*. (2认同)

fre*_*low 24

如何在assign成员函数?

some_vector.assign(some_vector.size(), 0);
Run Code Online (Sandbox Code Playgroud)

  • OP希望重设现有值,但是想要调整大小并重设这些值时,您的答案会更好。谢谢! (2认同)

unw*_*ind 12

如果它只是一个整数向量,我首先尝试:

memset(&my_vector[0], 0, my_vector.size() * sizeof my_vector[0]);
Run Code Online (Sandbox Code Playgroud)

它不是很C++,所以我相信有人会提供这样做的正确方法.:)

  • 您最好添加检查vector是否为空并且在这种情况下不执行任何操作.计算空向量的&buf [0]可以在STL代码中生成断言. (4认同)
  • 由于标准(2003 TC1)保证std :: vector在内存中是连续的,所以应该没问题.如果您的c ++库不符合2003 TC1,那么请不要使用它. (3认同)
  • @Mario:我不会发布这个,除非那是真的,当然也被认为是众所周知的.:)但谢谢. (2认同)

Yau*_*nka 6

我有同样的问题,但相当短vector<bool>(afaik 标准允许在内部实现它,而不仅仅是一个连续的布尔元素数组)。因此,我重复了 Fabio Fracassi 稍作修改的测试。结果如下(次,秒):

            -O0       -O3
         --------  --------
memset     0.666     1.045
fill      19.357     1.066
iterator  67.368     1.043
assign    17.975     0.530
for i     22.610     1.004
Run Code Online (Sandbox Code Playgroud)

所以显然对于这些尺寸,vector<bool>::assign()速度更快。用于测试的代码:

#include <vector>
#include <cstring>
#include <cstdlib>

#define TEST_METHOD 5
const size_t TEST_ITERATIONS = 34359738;
const size_t TEST_ARRAY_SIZE = 200;

using namespace std;

int main(int argc, char** argv) {

    std::vector<int> v(TEST_ARRAY_SIZE, 0);

    for(size_t i = 0; i < TEST_ITERATIONS; ++i) {
#if TEST_METHOD == 1
        memset(&v[0], false, v.size() * sizeof v[0]);
#elif TEST_METHOD == 2
        std::fill(v.begin(), v.end(), false);
   #elif TEST_METHOD == 3
        for (std::vector<int>::iterator it=v.begin(), end=v.end(); it!=end; ++it) {
            *it = 0;
        }
   #elif TEST_METHOD == 4
      v.assign(v.size(),false);
   #elif TEST_METHOD == 5
      for (size_t i = 0; i < TEST_ARRAY_SIZE; i++) {
          v[i] = false;
      }
#endif
    }

    return EXIT_SUCCESS;
}
Run Code Online (Sandbox Code Playgroud)

我在 Ubuntu 17.10 上使用了 GCC 7.2.0 编译器。用于编译的命令行:

g++ -std=c++11 -O0 main.cpp
g++ -std=c++11 -O3 main.cpp
Run Code Online (Sandbox Code Playgroud)


ntt*_*tar 5

尝试

std::fill
Run Code Online (Sandbox Code Playgroud)

并且

std::size siz = vec.size();
//no memory allocating
vec.resize(0);
vec.resize(siz, 0);
Run Code Online (Sandbox Code Playgroud)