Złożoność sqrt() z STL

Złożoność sqrt() z STL
AR
  • Rejestracja:ponad 12 lat
  • Ostatnio:prawie 9 lat
  • Postów:50
0

Jaka jest złożoność operacji sqrt() z C++11?

Kopiuj
long long int n;
cin >> n;
long long int p = sqrt(n);
Endrju
  • Rejestracja:około 22 lata
  • Ostatnio:ponad rok
2

To nie jest żaden STL.

Jaka złożoność? Standard nie definiuje żadnych wymagań czasowych ani pamięciowych dla std::sqrt.

W praktyce na x86 kompilator może wygenerować jedną instrukcję do obliczania pierwiastka (np. sqrtsd, te instrukcje to są dziesiątki cykli).


"(...) otherwise, the behavior is undefined".
edytowany 2x, ostatnio: Endrju
Zobacz pozostałe 2 komentarze
AR
Jeżeli wczytam K liczb i wypiszę pierwiastek każdej z tych liczb to złożoność będzie O(K) czy większa?
twonek
Te zadania są tak pomyślane, że jeżeli naprawdę musisz to zrobić to na pewno sqrt nie będzie wąskim gardłem. Pokaż treść zadadania btw.
YU
@Archimondei, całość wykona się w O(K). Czas sqrt to O(1).
_13th_Dragon
@Archimondei, czy przypadkiem nie masz coś w stylu for(int i=2;i<=sqrt(N);++i) ?
AR
Yurai, dzięki. _13th_Dragon, nie, ale wiem, że w takiej sytuacji wystarczy podnieść obie strony nierówności do kwadratu, żeby otrzymać i*i <= N
Azarien
  • Rejestracja:ponad 21 lat
  • Ostatnio:2 minuty
1

Jaka jest złożoność operacji sqrt() z C++11?
Złożoność jest zapewne O(1), czyli niezależna od wartości n.
Choć standard tego chyba nie zapewnia.

edytowany 1x, ostatnio: Azarien
Wibowit
  • Rejestracja:około 20 lat
  • Ostatnio:około 9 godzin
0
Azarien napisał(a):

Jaka jest złożoność operacji sqrt() z C++11?
Złożoność jest zapewne O(1), czyli niezależna od wartości n.
Choć standard tego chyba nie zapewnia.

Schodząc na najniższy poziom, czas wykonywania instrukcji liczącej pierwiastek na procesorze jest niekoniecznie stały, podobnie jak spora część instrukcji które wykonują się długo. Np patrząc na: http://agner.org/optimize/instruction_tables.pdf FSQRT na Intel Haswell dostajemy Latency 10 - 23 i Reciprocal throughput 8 - 17.

Złożoności mają sens głównie gdy mówimy o rozmiarach danych dążących do nieskończoności. Procesor natomiast operuje tylko i wyłącznie na małych porcjach. Żeby policzyć sobie pierwiastek z liczby N-bitowej (gdzie N to dowolna dodatnia liczba całkowita), trzeba sobie zrobić do tego algorytm i jemu będzie można policzyć złożoność.

Różnica między czasem optymistycznym a pesymistycznym jest pewną stałą, więc ogólnie można powiedzieć, że każda instrukcja ma złożoność O(1). Wydaje się to być trochę niedokładne, ale jeśli ktoś wie jak działają komputery to niedokładności widzi znacznie więcej. Nowoczesne procesory są superskalarne, czyli mogą wykonywać wiele instrukcji naraz (to jest ograniczone stałą zależną od projektu procesora), pod warunkiem, że są one niezależne. Czas dostępu do pamięci zależy od tego jak daleko znajduje się ona od rdzenia - najszybszy dostęp jest do pamięci podręcznej pierwszego poziomu, wolny dostęp jest do pamięci głównej, ale na upartego można i zmapować sobie zasób dyskowy (memory mapped files) lub sieciowy na przestrzeń adresową. Niuanse tego typu zmieniają się z architektury na architekturę i to także w obrębie jednego producenta. Przejmowanie się nimi spowodowałoby, że liczenie złożoności obliczeniowej urastałoby do rangi misji, dlatego nie uwzględnia się ich w złożoności. Duże składniki (typu 'n', 'sqrt(n)', itp) zwykle i tak dominują nad nawet dużymi różnicami w stałej złożoności. Dopiero gdy algorytmy różnią się małym składnikiem (typu 'log(n)') to można sprawdzać czy teoretycznie wolniejszy algorytm nie jest przypadkiem szybszy dzięki niższej stałej.


"Programs must be written for people to read, and only incidentally for machines to execute." - Abelson & Sussman, SICP, preface to the first edition
"Ci, co najbardziej pragną planować życie społeczne, gdyby im na to pozwolić, staliby się w najwyższym stopniu niebezpieczni i nietolerancyjni wobec planów życiowych innych ludzi. Często, tchnącego dobrocią i oddanego jakiejś sprawie idealistę, dzieli od fanatyka tylko mały krok."
Demokracja jest fajna, dopóki wygrywa twoja ulubiona partia.
Azarien
  • Rejestracja:ponad 21 lat
  • Ostatnio:2 minuty
1

Np patrząc na: http://agner.org/optimize/instruction_tables.pdf FSQRT na Intel Haswell dostajemy Latency 10 - 23 i Reciprocal throughput 8 - 17.

Pod warunkiem że wiemy, że użyta będzie akurat instrukcja fsqrt. A to może zależeć od parametrów kompilacji, od wersji kompilatora...

sqrt.png

Endrju
W x86 jest do tego 5 instrukcji: fsqrt (x87), sqrtss/sqrtps (SSE), sqrtsd/sqrtpd (SSE2). Ta pierwsza nigdy nie powinna być używana w 21 wieku. W zależności od typu argumentu dla pojedynczej operacji zostanie użyte sqrtss (float) i sqrtsd (inne typy). Przy wektoryzacji zostaną użyte wersje packed (bez też można, ale po co). W zasadzie one wszystkie mają dość podobną liczbę cykli, tj. dużą.
Azarien
"ta pierwsza nigdy nie powinna być używana w 21 wieku" – czasami jest pożądane, by program na starszych procesorach też działał. zwłaszcza że AMD dość późno wprowadziło SSE2.
Endrju
Każdy procesor x86_64 ma SSE2. Ta architektura została wprowadzona 11 (!!) lat temu.
Azarien
jeszcze raz: czasami jest pożądane, by program na starszych procesorach też działał. a czasami wręcz wymagane.
Endrju
Jedyny sensowny use case x87 to long double.
0
Azarien napisał(a):

Np patrząc na: http://agner.org/optimize/instruction_tables.pdf FSQRT na Intel Haswell dostajemy Latency 10 - 23 i Reciprocal throughput 8 - 17.

Pod warunkiem że wiemy, że użyta będzie akurat instrukcja fsqrt. A to może zależeć od parametrów kompilacji, od wersji kompilatora...

a z tymi AVL co tam jest?
bo to też można użyć zamiast SSE2 w VS... od 2010 chyba.

Azarien
  • Rejestracja:ponad 21 lat
  • Ostatnio:2 minuty
0

a z tymi AVL co tam jest?

Chyba AVX?

sqrt.png

Ale ten kod się u mnie wywala już na vmovsd z błędem “Illegal Instruction”. Co oczywiście zrozumiałe.

vpiotr
Oczywiście ;-)

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.