Jaki jest najszybszy sposób na zresetowanie każdej wartości od a std::vector<int>
do 0 i utrzymanie początkowego rozmiaru wektorów?
Pętla for z operatorem []?
Jaki jest najszybszy sposób na zresetowanie każdej wartości od a std::vector<int>
do 0 i utrzymanie początkowego rozmiaru wektorów?
Pętla for z operatorem []?
Odpowiedzi:
std::fill(v.begin(), v.end(), 0);
v = std::vector<int>(vec_size,0)
) wydaje się nieco szybsze niż fill
na mojej maszynie
assign
.
Jak zawsze, gdy pytasz o najszybszy: Zmierz! Korzystając z powyższych metod (na Macu z Clangiem):
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 |
przy użyciu 100000 iteracji na wektorze 10000 int.
Edit: Jeśli zmiana spowoduje to zmiany liczby przekonująco wynikające razy można mieć trochę zaufania (nie tak dobre jak inspekcji końcowej kod montaż), że punktem odniesienia sztuczny nie został zoptymalizowany z dala całkowicie. Oczywiście najlepiej zepsuć wydajność w rzeczywistych warunkach. koniec Edytuj
dla odniesienia wykorzystany kod:
#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;
}
Wniosek: użyj std::fill
(ponieważ, jak inni powiedzieli, jest najbardziej idiomatyczny)!
assign
wolniej, z wyjątkiem niewielkich pojemnościach na libc++
. KOD coliru / paste
fill
wygląda okropnie. W tym teście jest on o dwa rzędy wielkości wolniejszy.
A co z assign
funkcją członka?
some_vector.assign(some_vector.size(), 0);
Jeśli to tylko wektor liczb całkowitych, najpierw spróbuję:
memset(&my_vector[0], 0, my_vector.size() * sizeof my_vector[0]);
To nie jest bardzo C ++, więc jestem pewien, że ktoś zapewni odpowiedni sposób na zrobienie tego. :)
::std::fill
Sposób rozszerza się do czegoś, co jest całkiem cholernie szybko, choć nieco na stronie kodowej bloaty ponieważ wszystko inline. Nadal bym go używał, ponieważ jest o wiele ładniej czytać.
Miałem to samo pytanie, ale dość krótkie vector<bool>
(afaik standard pozwala na implementację go wewnętrznie inaczej niż tylko ciągły zestaw elementów boolowskich). Dlatego powtórzyłem nieco zmodyfikowane testy Fabio Fracassi. Wyniki są następujące (czasy, w sekundach):
-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
Więc najwyraźniej dla tych rozmiarów vector<bool>::assign()
jest szybszy. Kod użyty do testów:
#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;
}
Użyłem kompilatora GCC 7.2.0 na Ubuntu 17.10. Wiersz poleceń do kompilacji:
g++ -std=c++11 -O0 main.cpp
g++ -std=c++11 -O3 main.cpp