2013-10-04 9 views
7

Która metoda jest szybsza i ma mniej narzutów?czyszczenie wektora lub definiowanie nowego wektora, który jest szybszy

Metoda 1:

void foo() { 
    std::vector<int> aVector; 
    for (int i = 0; i < 1000000; ++i) { 
    aVector.clear(); 
    aVector.push_back(i); 
    } 
} 

Metoda 2:

void foo() { 
    for (int i = 0; i < 1000000; ++i) { 
    std::vector<int> aVector; 
    aVector.push_back(i); 
    } 
} 

Można powiedzieć, że przykład nie ma sensu! Ale to tylko fragment z mojego wielkiego kodu. W skrócie chcę wiedzieć lepiej jest

„stworzyć wektor raz i wyczyścić go do użytku”

lub

„Utwórz nowy wektor każdym razem”

UPDATE

Dzięki za sugestie, przetestowałem oba i tutaj są wyniki

Metoda 1:

$ time ./test1 

real 0m0.044s 
user 0m0.042s 
sys  0m0.002s 

Metoda 2:

$ time ./test2 

real 0m0.601s 
user 0m0.599s 
sys  0m0.002s 

Usuwanie wektor jest lepiej. Może to pomogę komuś innemu :)

+1

"czyszczenie wektora lub definiowanie nowego wektora, który jest szybszy" - porównuj go i poznaj. Nie można sformułować ogólnego stwierdzenia, ponieważ zależy to od wielu szczegółów związanych z platformą i implementacją. –

+0

Zgadzam się, ale chcę wiedzieć, jak g ++ generuje zoptymalizowany kod dla metod. Który z nich jest lepszy dla kompilatora? – mahmood

+2

Spodziewałbym się, że metoda "czysta" będzie szybsza, jeśli wystąpią jakiekolwiek różnice. –

Odpowiedz

6

Najprawdopodobniej numer clear() będzie szybszy, ponieważ zachowasz pamięć, która została przydzielona dla poprzednich push_back() s do wektora, tym samym zmniejszając potrzebę alokacji.

Usuwa również 1 wywołanie konstruktora i 1 wywołanie destruktora w pętli.

To wszystko ignorowanie tego, co optymalizator kompilatora może zrobić z tym kodem.

+0

+1 To, co zamierzałem napisać. –

0

Utworzenie pustego wektora jest bardzo mało narzutowe. Aby WZROST wektor o dużych rozmiarach jest potencjalnie dość drogi, ponieważ podwaja on rozmiar za każdym razem - więc wektor wejściowy 1M miałby 15-20 "kopii" wykonanych z bieżącej zawartości.

Dla trywialnych podstawowych typów, takich jak , narzut tworzenia obiektu i niszczenia obiektu jest "niczym", ale dla bardziej złożonego obiektu trzeba będzie wziąć pod uwagę konstrukcję i zniszczenie obiektu, która często jest znacznie większa niż "umieść obiekt w wektorze" i "usuń go z wektora". Innymi słowy, liczy się konstruktor i destruktor każdego obiektu.

Dla KAŻDEGO ", który jest szybszy z X lub Y", naprawdę trzeba ustalić punkt odniesienia dla okoliczności, które chcesz zrozumieć, chyba że jest BARDZO oczywiste, że jeden jest wyraźnie szybszy od drugiego (na przykład "wyszukiwanie liniowe lub wyszukiwanie binarne"). X elementów ", gdzie wyszukiwanie liniowe jest proporcjonalne do X, a wyszukiwanie binarne to log2 (x)).

Co więcej, jestem nieco zdezorientowany twoim przykładem - przechowywanie JEDNEGO elementu w wektorze jest dość kłopotliwe, a spora część z nich ponad int x = i; - Zakładam, że tak naprawdę nie oznacza to, że jako wzorzec. Innymi słowy, twoje konkretne porównanie nie jest sprawiedliwe, ponieważ wyraźne skonstruowanie wektorów 1M to więcej pracy niż skonstruowanie JEDNEGO wektora i wypełnienie go i wyczyszczenie go 1M razy.Jednakże, jeśli dokonaniu testu coś takiego:

void foo() { 
    for (int i = 0; i < 1000; ++i) { 
    std::vector<int> aVector; 
    for(j = 0; j < 1000; j++) 
    { 
     aVector.push_back(i); 
    } 
    } 
} 

[oraz odpowiednie zmiany do innego kodu] Spodziewam się, że wyniki będą dość podobne.

+0

std :: vector dynamicznie przydziela pamięć. Gdy procedury alokacji dynamicznej są nazywane bardzo często (jak w tym przykładzie), stają się dużym wąskim gardłem, nawet jeśli dane nie mają konstruktorów. Ponieważ clear() zwykle nie zmniejsza wewnętrznych danych, wywołanie clear będzie szybsze. – SigTerm

+0

@SigTerm: Tak, ale możesz również użyć 'aVector.resize (1000)', aby uniknąć tej alokacji. Ale tak jak powiedziałem, to zależy od tego, co jest zapisane w wektorze. –

+0

Jeśli celem jest użycie elementów 'push_back', wówczas' aVector.reserve (1000) 'będzie dokładniejsze. –