Qual è il modo più rapido per ripristinare ogni valore di uno std::vector<int>
a 0 e mantenere le dimensioni iniziali dei vettori?Il modo più veloce per reimpostare ogni valore di std :: vector <int> a 0
Un ciclo for con l'operatore []?
Qual è il modo più rapido per ripristinare ogni valore di uno std::vector<int>
a 0 e mantenere le dimensioni iniziali dei vettori?Il modo più veloce per reimpostare ogni valore di std :: vector <int> a 0
Un ciclo for con l'operatore []?
std::fill(v.begin(), v.end(), 0);
Guardando l'output dell'assieme, gcc srotola questo loop in modo da utilizzare i registri mmx per eseguire il dump in 16 byte alla volta fino a quando non si avvicina alla fine. Direi che è piuttosto veloce. La versione di memset salta a memset, che immagino sia altrettanto veloce. Userò il tuo metodo – Omnifarious
Tuttavia, saltare a memset è una singola istruzione, quindi utilizzarla comporterà una dimensione binaria più piccola. –
questo non è esattamente quello che l'OP chiedeva, ma semplicemente riassegnare il tuo vettore a uno nuovo della stessa dimensione ('v = std :: vector
Se è solo un vettore di interi, mi piacerebbe provare prima:
memset(&my_vector[0], 0, my_vector.size() * sizeof my_vector[0]);
Non è molto C++, quindi sono sicuro che qualcuno offrirà il modo corretto di fare questo. :)
Dato che lo standard (2003 TC1) garantisce che un file std :: vector è contiguo nella memoria, questo dovrebbe andare bene. Se la libreria C++ non è conforme al TC1 2003, non utilizzare questo. – Mario
@ Mario: Non avrei postato questo a meno che non fosse vero e presumibilmente noto, naturalmente. :) Ma grazie. – unwind
Ho controllato il montaggio. Il metodo ':: std :: fill' si espande a qualcosa che è dannatamente veloce, anche se un po 'sul lato del codice dal lato in cui tutto è in linea. Lo userò comunque perché è molto più bello da leggere. – Omnifarious
provare
std::fill
e anche
std::size siz = vec.size();
//no memory allocating
vec.resize(0);
vec.resize(siz, 0);
ridimensionare è molto bello – Nick
Come sempre quando si chiede circa più veloce: Misura! Utilizzando i metodi di cui sopra (su un Mac utilizzando 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 |
utilizzando 100000 iterazioni su un vettore di 10000 int.
Edit: Se changeing questi numeri plausibilmente muta i tempi risultanti si può avere un po 'di fiducia (non buono come ispezionare il codice di assemblaggio finale) che il parametro di riferimento artificiale non è stato ottimizzato via del tutto. Ovviamente è meglio messaggiare le prestazioni in condizioni reali. fine Modifica
di rinvio il codice utilizzato:
#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;
}
Conclusione: uso std::fill
(perché, come altri hanno detto il suo più idiomatica)!
+1. Questo particolare benchmark non è conclusivo, ma il punto è assolutamente corretto, dovresti scrivere un test delle prestazioni delle alternative in quanto verranno effettivamente utilizzate. Se non vi è alcuna differenza di prestazioni, utilizzare quella che è la fonte più semplice. –
"... non conclusivo ..." IMO questa inconcludenza di per sé è già un buon punto per fare benchmark, molto spesso l'Optimizer fa già un ottimo lavoro per il tipo di situazioni richieste dall'OP. E modificherei la tua ultima frase per leggere "Se non ci sono ** significative ** differenze di prestazioni ..." –
Con "non conclusivo" intendevo che solo perché erano tutti della stessa velocità in questo programma non significa necessariamente avranno tutti la stessa velocità nel programma del questionario. A parte qualsiasi altra cosa, dovresti essere sicuro che la memoria sia effettivamente azzerata: potrebbe essere che l'ottimizzatore fosse abbastanza intelligente da ingannare il test. Ma dal momento che non hai il programma del questionario, non è una mancanza di questa risposta :-) E hai perfettamente ragione, è molto facile passare il tempo agonizzando per una scelta che in realtà non fa alcuna differenza (o una differenza insignificante) una volta ottimizzato. –
E la funzione membro assign
?
some_vector.assign(some_vector.size(), 0);
L'OP voleva reimpostare i valori esistenti, ma la risposta è migliore quando si desidera ridimensionare _e resettare i valori. Grazie! –
Ho avuto la stessa domanda ma circa piuttosto breve vector<bool>
(afaik standard consente di implementare internamente diverso che una schiera continua di elementi booleane). Quindi ho ripetuto le prove leggermente modificate di Fabio Fracassi. I risultati sono i seguenti (i tempi, in secondi):
-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
Quindi, a quanto pare per queste dimensioni, vector<bool>::assign()
è più veloce. Il codice utilizzato per le prove:
#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;
}
ho usato GCC 7.2.0 del compilatore su Ubuntu 17.10. La riga di comando per la compilazione:
g++ -std=c++11 -O0 main.cpp
g++ -std=c++11 -O3 main.cpp
[std :: riempimento] (http://www.cplusplus.com/reference/algorithm/fill/) –
"più veloce", come in termini di prestazioni? O come più facile da implementare/mantenere? – TheGeneral