Qual é a maneira mais rápida de redefinir todos os valores de a std::vector<int>
para 0 e manter o tamanho inicial do vetor?
Um loop for com o operador []?
Qual é a maneira mais rápida de redefinir todos os valores de a std::vector<int>
para 0 e manter o tamanho inicial do vetor?
Um loop for com o operador []?
Respostas:
std::fill(v.begin(), v.end(), 0);
v = std::vector<int>(vec_size,0)
) parece um pouco mais rápido do que fill
na minha máquina
assign
.
Como sempre, quando você pergunta sobre o mais rápido: meça! Usando os métodos acima (em um Mac usando Clang):
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 |
usando 100000 iterações em um vetor de 10000 ints.
Editar: se a alteração desses números altera de maneira plausível os tempos resultantes, você pode ter alguma confiança (não tão boa quanto a inspeção do código de montagem final) de que o benchmark artificial não foi totalmente otimizado. Obviamente, é melhor medir o desempenho em condições reais. end Editar
para referência o código usado:
#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;
}
Conclusão: use std::fill
(porque, como outros já disseram que é o mais idiomático)!
assign
é mais lento, exceto por pequenas capacidades em diante libc++
. CODE coliru / paste
fill
parece terrível. São duas ordens de magnitude mais lentas neste teste.
E a assign
função de membro?
some_vector.assign(some_vector.size(), 0);
Se é apenas um vetor de números inteiros, eu tentaria primeiro:
memset(&my_vector[0], 0, my_vector.size() * sizeof my_vector[0]);
Não é muito C ++, por isso tenho certeza de que alguém fornecerá a maneira correta de fazer isso. :)
::std::fill
método se expande para algo bastante rápido, embora um pouco do lado do código, já que está tudo em linha. Eu ainda o usaria porque é muito melhor ler.
Eu tinha a mesma pergunta, mas bastante curta vector<bool>
(depois que o padrão permite implementá-lo internamente de maneira diferente do que apenas uma matriz contínua de elementos booleanos). Por isso, repeti os testes levemente modificados por Fabio Fracassi. Os resultados são os seguintes (tempos, em segundos):
-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
Então, aparentemente, para esses tamanhos, vector<bool>::assign()
é mais rápido. O código usado para testes:
#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;
}
Eu usei o compilador GCC 7.2.0 no Ubuntu 17.10. A linha de comando para compilar:
g++ -std=c++11 -O0 main.cpp
g++ -std=c++11 -O3 main.cpp