Nie wiem, czy to prawda, ale kiedy czytałem FAQ na temat jednej z problemów z udostępnianiem stron, znalazłem coś, co zwróciło moją uwagę:
Sprawdź metody wejścia / wyjścia. W C ++ używanie cin i cout jest zbyt wolne. Użyj ich, a zagwarantujesz, że nie będziesz w stanie rozwiązać żadnego problemu za pomocą przyzwoitej ilości danych wejściowych lub wyjściowych. Zamiast tego użyj printf i scanf.
Czy ktoś może to wyjaśnić? Czy naprawdę używanie scanf () w programach C ++ jest szybsze niż używanie cin >> coś ? Jeśli tak, czy dobrze jest używać go w programach C ++? Myślałem, że to specyficzne dla C, chociaż dopiero uczę się C ++ ...
c++
c
performance
io
zeroDivisible
źródło
źródło
Odpowiedzi:
Oto szybki test prostego przypadku: program do odczytywania listy liczb ze standardowego wejścia i XOR wszystkich liczb.
Wersja iostream:
wersja scanf:
Wyniki
Korzystając z trzeciego programu, wygenerowałem plik tekstowy zawierający 33 280 276 liczb losowych. Czasy realizacji to:
Zmiana ustawień optymalizacji kompilatora w ogóle nie zmieniła wyników.
Zatem: naprawdę istnieje różnica prędkości.
EDYCJA: Użytkownik clyfish wskazuje poniżej, że różnica prędkości jest w dużej mierze spowodowana funkcjami I / O iostream utrzymującymi synchronizację z funkcjami CI / O. Możemy to wyłączyć, dzwoniąc do
std::ios::sync_with_stdio(false);
:Nowe wyniki:
C ++ iostream wygrywa! Okazuje się, że ta wewnętrzna synchronizacja / opróżnianie jest tym, co zwykle spowalnia iostream we / wy. Jeśli nie mieszamy stdio i iostream, możemy to wyłączyć, a wtedy iostream jest najszybszy.
Kod: https://gist.github.com/3845568
źródło
iostream
przegrywa, gdy analizujesz więcej niż jedną liczbę całkowitą w jednymscanf
wywołaniu.http://www.quora.com/Is-cin-cout-slower-than-scanf-printf/answer/Aditya-Vishwakarma
Wydajność
cin
/cout
może być powolna, ponieważ muszą być zsynchronizowani z podstawową biblioteką C. Jest to niezbędne, jeśli mają być używane zarówno C IO, jak i C ++ IO.Jeśli jednak zamierzasz używać tylko C ++ IO, po prostu użyj poniższego wiersza przed operacjami IO.
Aby uzyskać więcej informacji na ten temat, zapoznaj się z odpowiednią dokumentacją libstdc ++ .
źródło
Prawdopodobnie scanf jest nieco szybszy niż używanie strumieni. Chociaż strumienie zapewniają duże bezpieczeństwo typów i nie muszą analizować ciągów formatu w czasie wykonywania, zwykle ma tę zaletę, że nie wymaga nadmiernego przydziału pamięci (zależy to od kompilatora i środowiska uruchomieniowego). To powiedziawszy, chyba że wydajność jest Twoim jedynym celem i znajdujesz się na ścieżce krytycznej, naprawdę powinieneś faworyzować bezpieczniejsze (wolniejsze) metody.
Jest bardzo smaczne artykuł napisany tutaj przez Herb Sutter „ Ciąg formatek z Manor Farm ”, który przechodzi w wielu szczegółach z wykonania ciągów formatujących jak
sscanf
ilexical_cast
i jakie rzeczy robili im działać wolniej lub szybciej. Jest to trochę analogiczne, prawdopodobnie do rodzaju rzeczy, które wpływałyby na wydajność między stylem IO w stylu C i stylem C ++. Główną różnicą w stosunku do elementów formatujących było bezpieczeństwo typów i liczba alokacji pamięci.źródło
Właśnie spędziłem wieczór pracując nad problemem w UVa Online (Factovisors, bardzo ciekawy problem, sprawdź to):
http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=35&page=show_problem&problem=1080
Otrzymywałem TLE (przekroczono limit czasu) na moje zgłoszenia. W tych witrynach z sędziami online do rozwiązywania problemów masz około 2-3 sekund na obsłużenie potencjalnie tysięcy przypadków testowych używanych do oceny Twojego rozwiązania. W przypadku problemów wymagających dużej mocy obliczeniowej, takich jak ten, liczy się każda mikrosekunda.
Używałem sugerowanego algorytmu (o którym możesz przeczytać na forach dyskusyjnych w witrynie), ale nadal otrzymywałem TLE.
Zmieniłem tylko „cin >> n >> m” na „scanf („% d% d ”, & n, & m)” i kilka małych „coutów” na „printfs”, a mój TLE zmienił się na „Zaakceptowano”!
Więc tak, może to mieć duże znaczenie, zwłaszcza gdy terminy są krótkie.
źródło
Jeśli zależy Ci na wydajności i formatowaniu ciągów, spójrz na bibliotekę FastFormat Matthew Wilsona .
edit - link do publikacji accu w tej bibliotece: http://accu.org/index.php/journals/1539
źródło
Istnieją implementacje stdio ( libio ), które implementują PLIK * jako strumień C ++ i fprintf jako parser formatu środowiska wykonawczego. IOstreams nie wymagają analizowania formatu w czasie wykonywania, wszystko to jest wykonywane w czasie kompilacji. Tak więc, przy współużytkowaniu backendów, rozsądnie jest oczekiwać, że iostreams jest szybszy w czasie wykonywania.
źródło
Tak, iostream jest wolniejszy niż cstdio.
Tak, prawdopodobnie nie powinieneś używać cstdio, jeśli tworzysz w C ++.
Powiedziawszy to, istnieją nawet szybsze sposoby na uzyskanie I / O niż scanf, jeśli nie zależy ci na formatowaniu, bezpieczeństwie typów, bla, bla, bla ...
Na przykład jest to niestandardowa procedura pobierania numeru z STDIN:
źródło
Instrukcje
cin
icout
ogólne użycie wydają się być wolniejsze niżscanf
iwprintf
C ++, ale w rzeczywistości są SZYBSZE!Chodzi o to, że w C ++ za każdym razem, gdy używasz
cin
icout
, domyślnie odbywa się proces synchronizacji, który zapewnia, że jeśli używasz obuscanf
iwcin
swoim programie, to oba będą ze sobą zsynchronizowane. Ten proces synchronizacji wymaga czasu. Stądcin
icout
WYGLĄDA na wolniejsze.Jeśli jednak proces synchronizacji nie
cin
jest wykonywany , jest szybszy niżscanf
.Aby pominąć proces synchronizacji, umieść w swoim programie następujący fragment kodu na samym początku
main()
:Odwiedź tę witrynę, aby uzyskać więcej informacji.
źródło
Problem polega na tym, że
cin
wiąże się to z dużym narzutem, ponieważ zapewnia warstwę abstrakcji nadscanf()
wywołaniami. Nie powinieneś używaćscanf()
overu,cin
jeśli piszesz oprogramowanie w C ++, ponieważ jest to pożądanecin
. Jeśli chcesz wydajności, prawdopodobnie i tak nie pisałbyś I / O w C ++.źródło
cin
naprawdę jest bardziej „abstrakcyjny” (w czasie wykonywania) niżscanf
? Nie sądzę ...scanf
musi interpretować ciąg formatu w czasie wykonywania, podczasiostream
gdy format zna format w czasie kompilacji.std::istream
jest skonfigurowane w czasie wykonywania (przez manipulatory we / wy lub przez ustawienie flag na samymistream
obiekcie). ZFILE*
drugiej strony obiekt nie ma takiego stanu, więc wywołaniescanf
w tym zakresie jest dużo bardziej stabilne.Na końcu pliku jest błąd, ale ten kod w C jest znacznie szybszy niż szybsza wersja C ++.
Oryginalny C ++ zajmował 30 sekund, a kod C 2 sekundy.
źródło
Oczywiście używanie cstdio na iostream jest śmieszne. Przynajmniej kiedy tworzysz oprogramowanie (jeśli już używasz c ++ zamiast c, to idź na całość i wykorzystaj jego zalety, a nie tylko cierpienie z powodu jego wad).
Ale w ocenie online, że nie tworzysz oprogramowania, tworzysz program, który powinien być w stanie robić rzeczy, które oprogramowanie Microsoft zajmuje 60 sekund w 3 sekundy !!!
Tak więc w tym przypadku złota zasada wygląda tak (oczywiście, jeśli nie masz jeszcze większych kłopotów, używając javy)
źródło
Nawet gdyby
scanf
był szybszy niżcin
, nie miałoby to znaczenia. Przez większość czasu będziesz czytać z dysku twardego lub klawiatury. Wprowadzenie surowych danych do aplikacji zajmuje rzędy wielkości więcej czasu niż ich przetwarzaniescanf
lubcin
ich przetworzenie.źródło
iostream
jest wolniejszy niż dysk twardy. Tak, to jest do bani.