Komputery Okna Internet

Co oznacza złożoność? Jaka jest trudność wydobycia? Używając Bitcoina jako przykładu. O(n) - złożoność liniowa

Jaka jest trudność wydobycia? Używając Bitcoina jako przykładu.

Wydobywanie kryptowalut może być bardzo opłacalną inwestycją. Aby jednak zarabiać na wydobywaniu walut, musisz dobrze rozumieć niuanse tej branży. Jedną z najważniejszych koncepcji dla każdego górnika jest trudność wydobycia. Dochód zależy bezpośrednio od trudności wydobycia. W artykule szczegółowo opisano, na czym polega trudność wydobycia, jak powstaje i od czego zależy.

Co oznacza termin „trudności w górnictwie”?

Wydobywanie kryptowalut to proces polegający na generowaniu nowych bloków łańcucha blockchain i rejestrowaniu transakcji. Górników można porównać do księgowych, którzy stale pracują nad tym, aby swoje księgi były na bieżąco, rejestrując wszystkie przelewy. Ale każda praca musi być opłacana. Górnicy otrzymują nagrodę od systemu w postaci monet wydobytej waluty.

Jedną z cech kryptowalut jest ich deflacyjny charakter. Oznacza to, że łączna liczba wydobytych monet nie może przekroczyć liczby określonej w kodzie programu. Na przykład maksymalna liczba Bitcoinów wynosi 21 milionów monet. Co więcej, ostatni Bitcoin zostanie wydobyty dopiero w 2140 roku. Pomimo dużej liczby górników, co 10 minut wydobywa się jedynie 12,5 BTC. Monety te są rozdzielane wśród górników zgodnie z wydatkowaną mocą obliczeniową. Nagroda za podpisany blok nie wzrasta (a nawet zmniejsza się o połowę co 4 lata). A jeśli liczba górników wzrasta, to dochód każdego górnika proporcjonalnie maleje. Wraz z pojawieniem się coraz większej liczby nowych kopaczy kryptowalut rośnie konkurencja o ograniczone nagrody.

Aby jasno zobrazować tę sytuację, wprowadzono wyliczony parametr sieci kryptowalut „trudność wydobycia”. Trudność wydobycia to miara, która odzwierciedla, jak trudno jest rozwiązać problem matematyczny, aby podpisać blok i otrzymać za to nagrodę. Poziom trudności jest automatycznie przeliczany po upływie określonego czasu. Dla każdej kryptowaluty jest inaczej. Na przykład trudność wydobycia Bitcoinów jest przeliczana co 2016 bloków, których wydobycie zajmuje około 2 tygodni. Zgodnie z kodem programu trudność jest dostosowana tak, aby wyszukiwanie kolejnego bloku trwało około 10 minut, niezależnie od liczby górników i całkowitego hashrate'u.

Trudność jest automatycznie zwiększana, jeśli wyszukiwanie ostatnich bloków z 2016 roku trwało krócej niż dwa tygodnie. Sugeruje to, że wzrosła całkowita moc obliczeniowa urządzeń górniczych. I odwrotnie, sygnałem do zmniejszenia złożoności będzie spowolnienie wyszukiwania bloków z 2016 r., ponieważ spadł hashrate wszystkich urządzeń. Rezultatem jest ścisła kontrola nad szybkością emisji nowych monet.

Gdzie znaleźć trudności z wydobyciem. Trudność wydobycia 10 najlepszych kryptowalut.

Trudność wydobycia jest wskaźnikiem dynamicznym, który jest okresowo przeliczany. Wraz ze wzrostem mocy obliczeniowej sprzętu górniczego rośnie jego złożoność. Aktualnych informacji na temat stanu trudności wydobycia kryptowaluty najlepiej szukać na oficjalnych stronach walut. Może to być jednak trudne. Linki do statystyk wydobycia są czasami trudne do znalezienia nawet na oficjalnych stronach internetowych. Aby uprościć proces, stworzono serwisy agregatorów informacji statystycznych o wszystkich kryptowalutach. Gromadzą, przetwarzają i publikują aktualne dane nie tylko na temat trudności wydobycia, ale także kilkudziesięciu innych wskaźników: ceny, kapitalizacji, hashrate, rentowności, liczby transakcji i tak dalej.

Aktualne informacje na temat ponad 100 kryptowalut znajdziesz na stronach:

  • https://www.coinwarz.com/charts/difficulty-charts
  • https://bitinfocharts.com/ru/
Nazwa kryptowalutyKapitalizacja (11.12.2017Link do tabeli trudności*
Bitcoina$102 337 870 442 https://blockchain.info/ru/charts/difficulty

https://bitinfocharts.com/ru/comparison/difficulty-btc-nmc.html

https://www.coinwarz.com/difficulty-charts/bitcoin-difficulty-chart

Bitcoinowa gotówka $29 402 898 569 https://bitinfocharts.com/ru/comparison/bitcoin%20cash-difficulty.html

https://www.coinwarz.com/difficulty-charts/bitcoincash-difficulty-chart

Eter$28 727 632 599 https://bitinfocharts.com/ru/comparison/ethereum-difficulty.html

https://www.coinwarz.com/difficulty-charts/ethereum-difficulty-chart

Marszczyć$7 559 040 243 Wydobywanie niedostępne**
Litecoin$3 143 298 761 https://bitinfocharts.com/ru/comparison/litecoin-difficulty.html

https://www.coinwarz.com/difficulty-charts/litecoin-difficulty-chart

Kropla$2 603 868 832 https://bitinfocharts.com/ru/comparison/dash-difficulty.html

https://www.coinwarz.com/difficulty-charts/dash-difficulty-chart

Klasyka Ethereum$1 867 386 337 https://bitinfocharts.com/ru/comparison/ethereum%20classic-difficulty.html

https://www.coinwarz.com/difficulty-charts/ethereum-classic-difficulty-chart

Monero$1 745 200 256 https://bitinfocharts.com/ru/comparison/monero-difficulty.html

https://www.coinwarz.com/difficulty-charts/monero-difficulty-chart

NEO$1 703 832 000 Wydobywanie niedostępne**
NEM$1 595 538 000 Wydobywanie niedostępne**

* Należy pamiętać, że trudność wydobycia zmienia się z biegiem czasu, więc różne witryny mogą udostępniać różne dane dotyczące trudności. Czasami różnica sięga 10-20% w zależności od waluty w dwóch różnych agregatorach. Jeśli szukasz wskaźnika trudności wydobycia nie tylko dla zaspokojenia ciekawości, ale w celach praktycznych, to skup się na średnich liczbach. Na przykład, jeśli prognozujesz zmiany w trudnościach wydobycia w przyszłości w oparciu o dynamikę historyczną, wówczas bardziej sensowne będzie zebranie danych za ostatnie sześć miesięcy do roku, a nie za dwa do czterech tygodni.

** Niektórych kryptowalut nie można wydobywać w tradycyjnym sensie. Niektórzy korzystają z wydobycia POS, w którym odsetki są okresowo naliczane od monet w portfelu. Aby wydobyć POS, nie musisz kupować specjalistycznego sprzętu i wydawać pieniędzy na prąd. Inne kryptowaluty (na przykład Ripple) zostały już w pełni wydobyte i podlegają jedynie redystrybucji pomiędzy właścicielami.

Trudność wydobycia: na co wpływa i dlaczego rośnie.

Trudność wydobycia określa dochód górnika. Liczba wydobytych monet jest odwrotnie proporcjonalna do trudności wydobycia. Jeśli trudność sieci wzrośnie o 20%, wówczas dochód każdego górnika z kryptowaluty zostanie zmniejszony o 20%.

Na przykład ASIC do wydobywania bitcoinów antminer s7 w połowie 2017 r. (a dokładniej z trudem na dzień 1 lipca 2017 r.) wydobywał 0,06 BTC miesięcznie. Jednak złożoność sieci Bitcoin stale rośnie. Od 1 listopada 2017 r. ten sam sprzęt będzie już produkował 0,026 BTC miesięcznie. Dochody górnika w ciągu zaledwie 4 miesięcy spadły o ponad połowę.

Jednak nawet tygodniowa redukcja dochodów nie powoduje, że inwestycje w górnictwie stają się mniej atrakcyjne. Przychody w kryptowalutach są częściowo kompensowane przez wzrost kursu wymiany na fiat. W naszym przykładzie 1 lipca kurs Bitcoina wynosił 2400 dolarów, a 1 listopada notowania wzrosły do ​​prawie 6700 dolarów. Okazuje się, że dochody fiducjarnych górników wzrosły nawet pomimo szybkiego wzrostu złożoności wydobycia.

Taka jest logika twórców kryptowalut o dynamicznej złożoności. I chociaż nie ma bezpośredniego związku pomiędzy ceną waluty a trudnością jej wydobycia, nadal istnieje związek pośredni. Zakłada się, że wzrost złożoności oznacza wzrost popularności kryptowalut wśród ogółu społeczeństwa. Ktoś, kto dowie się o zdecentralizowanych walutach, spróbuje je wydobywać. Doprowadzi to do większej złożoności. Ale jednocześnie istnieje duże prawdopodobieństwo wzrostu popytu, a tym samym kursu walutowego. Okazuje się, że rosnące zainteresowanie społeczeństwem stymuluje zarówno wzrost kursu walutowego, jak i wzrost złożoności wydobycia.

Z technicznego punktu widzenia wskaźnik trudności wydobycia zależy od:

  • hashrate sieci (liczba i moc obliczeniowa sprzętu wszystkich górników);
  • prędkość wydobycia bloków 2016;

Wszystkie trzy wskaźniki są ze sobą bezpośrednio powiązane. Rozwój hashrate sieci oznacza, że ​​do branży wydobywczej dołączyli nowi uczestnicy, a konkurencja wzrosła. Wraz ze wzrostem liczby górników czas spędzony na poszukiwaniu kolejnego bloku maleje. Po bloku 2016 następuje ponowne przeliczenie trudności wydobycia. Zmianę wskaźnika opisuje następujący wzór:

Trudność w wydobywaniu bitcoinów.

Wzrost złożoności wynika z szeregu czynników, które są ze sobą ściśle powiązane:

  • rozwój chipów ASIC i wejście na rynek bardziej produktywnych modeli;
  • popularyzacja Bitcoina i napływ nowych górników;
  • wysoki zwrot z inwestycji w górnictwo ze względu na szybki wzrost kursu Bitcoina w stosunku do dolara;
  • transfer mocy obliczeniowej z innych walut, których notowania spadają lub rosną wolniej niż Bitcoin;
  • inne czynniki;

Od 2016 roku trudność wydobycia Bitcoina wzrosła 5-6 razy. Wzrost trwał niemal nieprzerwanie. Dopiero w sierpniu 2017 r. po raz pierwszy od roku nastąpił spadek wskaźnika. Być może miał na to wpływ sierpniowy SegWit Bitcoina, który zmusił część górników do przeniesienia mocy na altcoiny.

6 odpowiedzi

Złożoność jest zawsze określana w odniesieniu do określonej zmiennej lub zestawu zmiennych. Kiedy więc norma mówi o wstawieniu stałego czasu, mówimy o stałym czasie w stosunku do liczby elementów na liście. Oznacza to, że wstawienie O(1) oznacza, że ​​liczba elementów znajdujących się na liście nie wpływa na ogólną złożoność wstawień. Lista może zawierać 500 lub 50000000 elementów, a złożoność operacji wstawiania będzie taka sama.

Na przykład std::list zawiera wstawki i usunięcia O(1); liczba elementów na liście nie zależy od złożoności wstawek. Jednak złożoność alokacji pamięci może zależeć od liczby rzeczy, które zostały już przydzielone. Ale ponieważ O(1) mówi o liczbie elementów na liście, nie obejmuje tego. A tego się nie zakłada, bo wtedy mierzylibyśmy złożoność alokatora pamięci, a nie strukturę danych.

W skrócie: to jest inny wymiar.

Oznacza to, że możemy zaimplementować nasz algorytm tak mocno, jak nam się podoba, łącznie z takim, w którym czas nie jest w rzeczywistości stały w żadnym pragmatycznym sensie, ale gdzie przestrzegamy liczby „operacji” na zawartych obiektach.

Złożoność nie jest określona w odniesieniu do implementacji. Jest on określony w odniesieniu do algorytmów. Nie ma znaczenia, że ​​kontekst może się zmieniać, ponieważ środowisko wykonawcze nie jest trudnym zadaniem.

Jak powyżej, możesz zaimplementować std::list z alokatorem pamięci, który wynosi O(log(n)) w odniesieniu do usunięć (gdzie n to liczba alokacji). Jednak usunięcie elementu z listy nadal będzie O(1) w odniesieniu do liczby elementów na liście.

Nie myl złożoności z ogólną wydajnością. Celem złożoności jest posiadanie wspólnej metryki dla algorytmów dotyczących różnych zmiennych. Celem programisty, który chce, aby jego kod działał szybko, jest znalezienie rozsądnej implementacji algorytmu, który odpowiada złożoności wymaganej do osiągnięcia tej wydajności.

Złożoność jest narzędziem oceny efektywności algorytmu. Złożoność nie oznacza, że ​​możesz przestać myśleć.

Co dokładnie oznacza „amortyzacja”?

Jak rozumiem, stała złożoność oznacza, że ​​operacja to O(1): możesz z góry określić, ile operacji atomowych (odczyt/zapis, instrukcje montażu, cokolwiek) zostanie wykonanych. A to oszacowanie jest wspólną granicą dla wszystkich możliwych stanów obiektu docelowego. Jest tu pewien haczyk: w środowisku wielowątkowym nie można przewidzieć przełączników przepływu, więc można jedynie wyciągnąć pewne wnioski na temat czasu działania, jaki upłynął w systemie operacyjnym czasu rzeczywistego.

Jeśli chodzi o amortyzowaną stałą złożoność, jest jeszcze słabsza. Zapisując podsumowanie odpowiedzi, masz pewność, że Twoja operacja jest w toku. Oznacza to, że liczba operacji elementarnych dla N kolejnych operacji wynosi O(N) . Oznacza to, że liczba operacji elementarnych wynosi około O(1), ale pozwala na rzadkie skoki. Na przykład dodanie elementu do ogona wektora jest zwykle trwałe, ale czasami wymagane jest dodatkowe podnoszenie ciężarów; posiadanie amortyzowanego stałego czasu oznacza, że ​​dodatkowa operacja nie jest wykonywana tak często i zajmuje przewidywalną ilość czasu, tak że całkowity czas operacji N nadal wynosi O(N) . Oczywiście tutaj obowiązuje ten sam haczyk.

Zatem odpowiadając na Twoje pytania:

  • Złożone gwarancje standardu w rzeczywistości dotyczą tylko liczby instrukcji kodu maszynowego wymaganych do wykonania operacji i nie oznaczają, że czas wykonania jest w jakikolwiek sposób ograniczony. (Istotnie, do niedawna C++ nie miał nawet wskaźnika tematu związanego z językiem, więc ze standardowego punktu widzenia C++, do tego czasu program był wykonywany na wyspecjalizowanej maszynie C++.)
  • Amortyzacja jest „ograniczona do stałej średniej”, co zwykle ma miejsce w przypadku prawie zawsze stałego, ograniczonego czasu pracy z pewnymi dość rzadkimi odchyleniami.

Edytować:
Możesz spojrzeć na przykład na sekcję 23.1 standardu C++:

Wszystkie wymagania dotyczące złożoności w tej sekcji są określone wyłącznie w kategoriach liczby operacji na zawartych obiektach.

kiedy mówi się, że operacja ma „stałą złożoność”, zwykle odnosi się to przede wszystkim do złożoności czasowej. Mógłbym odnosić się do złożoności przestrzennej, ale w takim przypadku byłoby to wyraźnie określone jako normalne.

Teraz złożoność operacji odnosi się do tego, ile czasu na zakończenie operacji wzrośnie, gdy wzrośnie liczba elementów przetwarzanych w operacji. W przypadku operacji o stałej złożoności funkcja zajmie tyle samo czasu, niezależnie od tego, czy przetwarzane są zero elementów, czy dziesięć milionów elementów.

    swap() ma stałą złożoność, ponieważ niezależnie od tego, ile elementów znajduje się w wektorze, operacja zajmie tyle samo czasu.

    kliknij listę. jest stałą złożonością, ponieważ choć alokacja nowego elementu może zająć trochę czasu, to czas alokacji nie wzrasta, ponieważ lista zawiera 10 milionów elementów (przynajmniej nie w sensie algorytmicznym - oczywiście, jeśli wolna pamięć się powiększy i bardziej wyczerpana, alokacja może trwać dłużej, ale z algorytmicznego punktu widzenia jest to nieskończona ilość pamięci).

    push_back() na wektorze nazywana jest stałą „amortyzowaną”, ponieważ w normalnym przypadku, gdy realokacja nie powinna nastąpić, czas trwania operacji nie jest powiązany z liczbą elementów znajdujących się już w wektorze — jest to ta sama ilość czas potrzebny na dodanie nowego elementu do wektora o długości zerowej w stosunku do wektora o długości 10 milionów. Jeśli jednak zajdzie potrzeba ponownego rozmieszczenia wektora, konieczne będzie posiadanie kopii istniejących elementów i nie jest to operacja ciągła - jest to operacja liniowa. Ale wektor powinien być zaprojektowany w taki sposób, aby realokacje następowały rzadko, tak aby można je było amortyzować podczas wielu operacji push_back().

ale wykonanie push_back na wektorze jest jeszcze bardziej nieprzewidywalne. W większości przypadków będzie to bardzo szybkie, ale od czasu do czasu konieczne będzie ponowne przydzielenie miejsca na wszystkie dane i skopiowanie każdego elementu do nowej lokalizacji. Jest więc mniej przewidywalny pod względem czasu wykonania niż sama list::push_front, ale nadal nazywa się go trwałym (amortyzowanym). Średnio dodanie dużej ilości danych do wektora będzie wymagało złożoności niezależnej od dodanej ilości, dlatego nazywa się to czasem „stałym amortyzowanym”. (Prawidłowy?)

Złożoność wynosi O(1) - stała (uwzględniająca złożoność czasową) oznacza, że ​​czas wykonania algorytmu nie jest powiązany z wielkością problemu.

Zatem wyszukiwanie wartości w strukturze zahaszowanej to O(1), ponieważ czas potrzebny na to jest niezależny od liczby jej wartości. Jednak to samo nie dotyczy listy połączonej, ponieważ musimy przeskanować wartości (których liczba zmienia się wraz ze wzrostem liczby elementów), aby znaleźć naszą wartość.

W przypadku 3, gdy kopiuje każdy element, nie jest to operacja O(1), ale operacja O(N) (ale w większości przypadków jest to O(1, więc zwykle jest stała). Amortyzacja uwzględnia to, zauważając, że algorytm zwykle kończy się w czasie O(1) i rzadko wpada w ten przypadek O(N).

Prawdopodobnie nie raz spotkałeś się z zapisami takimi jak O(log n) lub słyszałeś określenia takie jak „logarytmiczna złożoność obliczeniowa” odnoszące się do niektórych algorytmów. A jeśli nadal nie rozumiesz, co to oznacza, ten artykuł jest dla Ciebie.

Ocena trudności

Złożoność algorytmów mierzy się zwykle czasem ich wykonania lub zużyciem pamięci. W obu przypadkach złożoność zależy od wielkości danych wejściowych: tablica 100 elementów zostanie przetworzona szybciej niż podobna tablica 1000. Niewiele osób interesuje jednak dokładny czas: zależy to od procesora, typu danych , język programowania i wiele innych parametrów. Ważna jest tylko złożoność asymptotyczna, czyli złożoność, gdy rozmiar danych wejściowych dąży do nieskończoności.

Załóżmy, że jakiś algorytm musi wykonać 4n 3 + 7n operacji warunkowych, aby przetworzyć n elementów danych wejściowych. W miarę wzrostu n na ostateczny czas pracy będzie znacznie większy wpływ podniesienie n do sześcianu niż pomnożenie go przez 4 lub dodanie 7n. Następnie mówią, że złożoność czasowa tego algorytmu wynosi O(n 3), czyli zależy sześciennie od wielkości danych wejściowych.

Użycie dużej litery O (lub tak zwanej notacji O) wywodzi się z matematyki, gdzie używa się jej do porównywania asymptotycznego zachowania funkcji. Formalnie O(f(n)) oznacza, że ​​czas działania algorytmu (lub ilość zajętej pamięci) rośnie w zależności od rozmiaru danych wejściowych nie szybciej niż pewna stała pomnożona przez f(n).

Przykłady

O(n) - złożoność liniowa

Na przykład algorytm znajdowania największego elementu w nieposortowanej tablicy ma tę złożoność. Będziemy musieli przejrzeć wszystkie n elementów tablicy, aby zrozumieć, który z nich jest maksymalny.

O(log n) - złożoność logarytmiczna

Najprostszym przykładem jest wyszukiwanie binarne. Jeśli tablica jest posortowana, możemy sprawdzić, czy zawiera określoną wartość, stosując metodę halvingu. Sprawdźmy środkowy element, jeśli jest większy od tego, którego szukamy, to drugą połowę tablicy odrzucimy – na pewno go tam nie ma. Jeśli jest mniej, to odwrotnie - odrzucimy początkową połowę. I tak będziemy dalej dzielić na pół, a na koniec sprawdzimy log n elementów.

O(n 2) - złożoność kwadratowa

Na przykład algorytm sortowania przez wstawianie ma tę złożoność. W wykonaniu kanonicznym składa się z dwóch zagnieżdżonych pętli: jednej przechodzącej przez całą tablicę i drugiej szukającej miejsca na kolejny element w już posortowanej części. Zatem liczba operacji będzie zależała od rozmiaru tablicy jako n * n, tj. n 2.

Istnieją inne stopnie trudności, ale wszystkie opierają się na tej samej zasadzie.

Zdarza się również, że czas działania algorytmu w ogóle nie zależy od wielkości danych wejściowych. Następnie złożoność jest oznaczana jako O(1) . Na przykład, aby określić wartość trzeciego elementu tablicy, nie trzeba pamiętać elementów ani wielokrotnie ich przeglądać. Zawsze wystarczy poczekać na trzeci element w strumieniu danych wejściowych i taki będzie wynik, którego obliczenie zajmuje tyle samo czasu dla dowolnej ilości danych.

To samo dotyczy oceny pamięci, gdy jest to ważne. Jednak algorytmy mogą zużywać znacznie więcej pamięci podczas zwiększania rozmiaru danych wejściowych niż inne, ale nadal działają szybciej. I wzajemnie. Pomaga to wybrać najlepsze sposoby rozwiązania problemów w oparciu o aktualne warunki i wymagania.