Patrząc na dane wyjściowe asemblera, gcc faktycznie rozwija tę pętlę i używa rejestrów mmx do zrzucania 16 bajtów jednocześnie, aż zbliży się do końca. Powiedziałbym, że to dość szybko. Wersja zestawu przeskakuje do zestawu, który, jak sądzę, jest równie szybki. Użyłbym twojej metody.
Wszechobecny
Ale przejście do memset jest pojedynczą instrukcją, więc użycie go spowoduje mniejszy rozmiar pliku binarnego.
Alexander Shishenko,
2
nie jest to dokładnie to, o co poprosił OP, ale po prostu ponowne przypisanie wektora do nowego tego samego rozmiaru ( v = std::vector<int>(vec_size,0)) wydaje się nieco szybsze niż fillna mojej maszynie
Yibo Yang,
1
Jest to najbardziej idiomatyczny sposób robienia tego, bardziej idiomatyczny niż używanie assign.
alfC
1
czy przypisanie go do nowego wektora powoduje alokację sterty? a następnie odrzucić przydział istniejącego wektora? Widziałem, że jest wolniejszy niż memset i wsp.
Conrad Jones
150
Jak zawsze, gdy pytasz o najszybszy: Zmierz! Korzystając z powyższych metod (na Macu z Clangiem):
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
+1. Ten konkretny test porównawczy nie jest rozstrzygający, ale kwestia jest absolutnie słuszna, powinieneś napisać test wydajności alternatyw, ponieważ będą one faktycznie wykorzystane. Jeśli nie ma różnicy w wydajności, użyj dowolnego z najprostszych źródeł.
Steve Jessop
3
„... nie rozstrzygające ...” IMO ta niejednoznaczność sama w sobie jest już dobrym punktem do robienia testów, częściej niż Optymalizator już wykonuje bardzo dobrą pracę w sytuacjach, o które pytał PO. I zmodyfikowałbym twoje ostatnie zdanie, aby brzmiało „Jeśli nie ma znaczącej różnicy w wydajności ...”
Ponadto, wow, jeśli zależy Ci na szybkości bez optymalizacji (co może być prawdopodobne, jeśli wdrażasz w trybie „debugowania”, co robią niektóre zespoły), fillwygląda okropnie. W tym teście jest on o dwa rzędy wielkości wolniejszy.
Kyle Strand
5
@KyleStrand: To nie jest tak, że wypełnienie jest okropne, to szablon, a kod jest generowany z -O0 w twojej jednostce tłumaczeniowej. Kiedy używasz memset, używasz kodu libc, który został skompilowany z -O3 (nawet jeśli kompilujesz swój kod z -O0). Jeśli zależy Ci na szybkości debugowania i korzystasz z szablonów, będziesz musiał użyć jawnej instancji szablonu w osobnym pliku, który skompilujesz z -O3
Ponieważ standard (2003 TC1) gwarantuje, że std :: wektor jest ciągły w pamięci, to powinno być w porządku. Jeśli twoja biblioteka c ++ nie jest zgodna z TC1 2003, nie używaj jej.
Mario
2
@Mario: Nie opublikowałbym tego, gdyby to nie była prawda i oczywiście założono, że jest dobrze znana. :) Ale dzięki.
odpręż się
1
Sprawdziłem zespół. ::std::fillSposó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ć.
Wszechobecny
4
Lepiej dodaj sprawdzenie, czy wektor jest pusty i nic nie rób w tym przypadku. Obliczanie & buf [0] dla pustego wektora może generować twierdzenia w kodzie STL.
Siergiej
4
próbować
std::fill
i również
std::size siz = vec.size();//no memory allocating
vec.resize(0);
vec.resize(siz,0);
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.6661.045
fill 19.3571.066iterator67.3681.043
assign 17.9750.530for i 22.6101.004
Więc najwyraźniej dla tych rozmiarów vector<bool>::assign()jest szybszy. Kod użyty do testów:
Odpowiedzi:
źródło
v = std::vector<int>(vec_size,0)
) wydaje się nieco szybsze niżfill
na mojej maszynieassign
.Jak zawsze, gdy pytasz o najszybszy: Zmierz! Korzystając z powyższych metod (na Macu z Clangiem):
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:
Wniosek: użyj
std::fill
(ponieważ, jak inni powiedzieli, jest najbardziej idiomatyczny)!źródło
assign
wolniej, z wyjątkiem niewielkich pojemnościach nalibc++
. KOD coliru / pastefill
wygląda okropnie. W tym teście jest on o dwa rzędy wielkości wolniejszy.A co z
assign
funkcją członka?źródło
Jeśli to tylko wektor liczb całkowitych, najpierw spróbuję:
To nie jest bardzo C ++, więc jestem pewien, że ktoś zapewni odpowiedni sposób na zrobienie tego. :)
źródło
::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ć.próbować
i również
źródło
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):Więc najwyraźniej dla tych rozmiarów
vector<bool>::assign()
jest szybszy. Kod użyty do testów:Użyłem kompilatora GCC 7.2.0 na Ubuntu 17.10. Wiersz poleceń do kompilacji:
źródło