web-dev-qa-db-ja.com

std :: vector <int>のすべての値を0にリセットする最速の方法

std::vector<int>のすべての値を0にリセットし、ベクトルの初期サイズを維持する最速の方法は何ですか?

[]演算子を使用したforループ?

158
std::fill(v.begin(), v.end(), 0);
279
Cat Plus Plus

いつものように最速について尋ねるとき:測定!上記の方法の使用(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    |

10000 intのベクトルで100000回の繰り返しを使用します。

編集:この数値を変更すると、結果の時間をもっともらしく変更できる場合、someの信頼を得ることができます(最終アセンブリの検査ほど良くありません)コード)人工的なベンチマークが完全に最適化されていないこと。もちろん、実際の条件下でパフォーマンスを測定することをお勧めします。 編集の終了

参考のために使用コード:

#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;
}

結論:std::fillを使用します(他の人が最も慣用的と言っているため)!

127
Fabio Fracassi

assignメンバー関数はどうですか?

some_vector.assign(some_vector.size(), 0);
23
fredoverflow

それが単なる整数のベクトルである場合、私は最初に試してみます:

memset(&my_vector[0], 0, my_vector.size() * sizeof my_vector[0]);

それはあまりC++ではないので、誰かがこれを行う適切な方法を提供すると確信しています。 :)

12
unwind

試してみる

std::fill

そしてまた

std::size siz = vec.size();
//no memory allocating
vec.resize(0);
vec.resize(siz, 0);
3
nttstar

私は同じ質問をしましたが、かなり短いvector<bool>(標準では、ブール要素の単なる連続配列とは異なる方法で内部的に実装することができます)。そのため、ファビオ・フラカッシによるわずかに修正されたテストを繰り返しました。結果は次のとおりです(時間、秒単位)。

            -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

したがって、これらのサイズでは、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;
}

Ubuntu 17.10でGCC 7.2.0コンパイラを使用しました。コンパイル用のコマンドライン:

g++ -std=c++11 -O0 main.cpp
g++ -std=c++11 -O3 main.cpp
1