Computer finestre Internet

Cosa significa complessità? Cos'è la difficoltà di mining? Usando Bitcoin come esempio. O(n) - complessità lineare

Cos'è la difficoltà di mining? Usando Bitcoin come esempio.

Il mining di criptovalute può essere un investimento molto redditizio. Ma per guadagnare denaro dall’estrazione di valuta, è necessario comprendere bene le sfumature del settore. Uno dei concetti più importanti per ogni minatore è la difficoltà del mining. Il reddito dipende direttamente dalla difficoltà dell'estrazione mineraria. In questo articolo viene descritto nel dettaglio cos'è la difficoltà di mining, come si forma e da cosa dipende.

Cosa significa il termine “difficoltà di mining”?

Il mining di criptovaluta è un processo che prevede la generazione di nuovi blocchi della catena blockchain e la registrazione delle transazioni. I minatori possono essere paragonati ai contabili che lavorano costantemente per tenere aggiornati i loro libri contabili registrando tutti i trasferimenti. Ma qualsiasi lavoro deve essere pagato. I minatori ricevono una ricompensa dal sistema sotto forma di monete della valuta minata.

Una delle caratteristiche delle criptovalute è la loro natura deflazionistica. Ciò significa che il numero totale di monete estratte non può superare il numero specificato dal codice del programma. Ad esempio, il numero massimo di Bitcoin è di 21 milioni di monete. Inoltre, l’ultimo Bitcoin verrà minato solo nel 2140. Nonostante il numero di minatori, ogni 10 minuti vengono estratti solo 12,5 BTC. Queste monete vengono distribuite tra i minatori in base alla potenza di calcolo spesa. La ricompensa per un blocco firmato non aumenta (e viene addirittura ridotta della metà ogni 4 anni). E se il numero dei minatori aumenta, allora il reddito di ogni singolo minatore diminuisce proporzionalmente. Con l’arrivo di sempre più nuovi minatori di criptovalute, la competizione per ricompense limitate sta crescendo.

Per dimostrare chiaramente questa situazione, è stato introdotto un parametro calcolato della “difficoltà di mining” della rete di criptovaluta. La difficoltà di mining è una metrica che riflette quanto sia difficile risolvere il problema matematico per firmare un blocco e ricevere una ricompensa per questo. La difficoltà viene ricalcolata automaticamente dopo un certo periodo di tempo. È diverso per ogni criptovaluta. Ad esempio, la difficoltà del mining di Bitcoin viene ricalcolata ogni 2016 blocchi, il cui mining richiede circa 2 settimane. Secondo il codice del programma, la difficoltà viene regolata in modo che la ricerca del blocco successivo richieda circa 10 minuti, indipendentemente dal numero di minatori e dall'hashrate totale.

La difficoltà aumenta automaticamente se la ricerca degli ultimi blocchi del 2016 è durata meno di due settimane. Ciò suggerisce che la potenza di calcolo totale dei dispositivi minerari è aumentata. Al contrario, un segnale per ridurre la complessità sarà un rallentamento nella ricerca dei blocchi 2016, poiché l’hashrate di tutti i dispositivi è diminuito. Il risultato è uno stretto controllo sulla velocità con cui vengono emesse le nuove monete.

Dove trovare difficoltà di mining. Difficoltà nel mining delle prime 10 criptovalute.

La difficoltà di mining è un indicatore dinamico che viene periodicamente ricalcolato. Con l’aumento della potenza di calcolo delle apparecchiature minerarie, aumenta anche la complessità. È meglio cercare informazioni aggiornate sullo stato della difficoltà di mining di criptovaluta sui siti ufficiali delle valute. Tuttavia, questo può essere difficile. I collegamenti alle statistiche minerarie a volte sono difficili da trovare anche sui siti ufficiali. Per semplificare il processo, sono stati creati siti web aggregatori di informazioni statistiche su tutte le criptovalute. Raccolgono, elaborano e pubblicano dati attuali non solo sulla difficoltà del mining, ma anche su diverse decine di altri indicatori: prezzo, capitalizzazione, hashrate, redditività, numero di transazioni e così via.

Informazioni aggiornate su più di 100 criptovalute possono essere trovate sui seguenti siti web:

  • https://www.coinwarz.com/charts/difficulty-charts
  • https://bitinfocharts.com/ru/
Nome della criptovalutaCapitalizzazione (11/12/2017Link alla tabella delle difficoltà*
Bitcoin$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

Bitcoin Contanti $29 402 898 569 https://bitinfocharts.com/ru/comparison/bitcoin%20cash-difficulty.html

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

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

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

Ondulazione$7 559 040 243 Estrazione non disponibile**
Litecoin$3 143 298 761 https://bitinfocharts.com/ru/comparison/litecoin-difficulty.html

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

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

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

Ethereum classico$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 Estrazione non disponibile**
NEM$1 595 538 000 Estrazione non disponibile**

* Tieni presente che la difficoltà di mining cambia nel tempo, quindi siti diversi potrebbero fornire dati di difficoltà diversi. A volte la differenza raggiunge il 10-20% in base alla valuta su due diversi aggregatori. Se stai cercando un indicatore della difficoltà di mining non solo per soddisfare la curiosità, ma per scopi pratici, concentrati sui numeri medi. Ad esempio, se stai facendo una previsione dei cambiamenti futuri nella difficoltà di mining sulla base delle dinamiche storiche, allora ha più senso prendere i dati dagli ultimi sei mesi a un anno, piuttosto che da due a quattro settimane.

** Alcune criptovalute non possono essere estratte nel senso tradizionale. Alcuni utilizzano il mining POS, in cui gli interessi maturano periodicamente sulle monete nel portafoglio. Per il mining POS non è necessario acquistare attrezzature specializzate o spendere soldi per l'elettricità. Altre criptovalute (ad esempio Ripple) sono già state completamente estratte e vengono solo ridistribuite tra i proprietari.

Difficoltà mineraria: cosa influisce e perché cresce.

La difficoltà dell’estrazione determina il reddito del minatore. Il numero di monete estratte è inversamente proporzionale alla difficoltà di mining. Se la difficoltà della rete aumenta del 20%, il reddito in criptovaluta di ogni singolo minatore si riduce del 20%.

Ad esempio, l'ASIC per il mining di bitcoin antminer s7 a metà del 2017 (più precisamente, con difficoltà dal 1 luglio 2017) ha estratto 0,06 BTC al mese. Ma la complessità della rete Bitcoin è in continua crescita. Dal 1° novembre 2017 la stessa attrezzatura produrrà già 0,026 BTC al mese. Il reddito del minatore è diminuito di oltre la metà in soli 4 mesi.

Ma anche una riduzione settimanale del reddito non rende gli investimenti minerari meno attraenti. Le entrate in criptovaluta sono parzialmente compensate dall’aumento del tasso di cambio rispetto al fiat. Nel nostro esempio, il 1° luglio il tasso di cambio del Bitcoin era di 2.400$, mentre il 1° novembre le quotazioni sono salite a quasi 6.700$. Si scopre che il reddito dei minatori fiat è aumentato nonostante il rapido aumento della complessità del mining.

Questa è la logica dei creatori di criptovalute con complessità dinamica. E sebbene non esista una relazione diretta tra il prezzo di una valuta e quanto sia difficile estrarla, esiste comunque una relazione indiretta. Si presume che l’aumento della complessità significhi un aumento della popolarità della criptovaluta tra la popolazione generale. Qualcuno che impara a conoscere le valute decentralizzate proverà a estrarre. Ciò comporterà una maggiore complessità. Ma allo stesso tempo, è molto probabile che la domanda aumenti e, di conseguenza, il tasso di cambio. Si scopre che il crescente interesse per la società stimola sia la crescita del tasso di cambio che l’aumento della complessità dell’attività mineraria.

Da un punto di vista tecnico l’indicatore di difficoltà di mining dipende da:

  • hashrate di rete (il numero e la potenza di calcolo delle apparecchiature di tutti i minatori);
  • velocità di mining di blocchi del 2016;

Tutti e tre gli indicatori sono direttamente correlati. La crescita dell’hashrate della rete significa che nuovi partecipanti si sono uniti al settore minerario e la concorrenza è aumentata. All’aumentare del numero di minatori, diminuisce il tempo impiegato nella ricerca del blocco successivo. Dopo il blocco 2016 la difficoltà di mining viene ricalcolata. La variazione dell’indicatore è descritta dal seguente schema:

Difficoltà di mining di Bitcoin.

L’aumento della complessità è dovuto ad una serie di fattori strettamente correlati:

  • sviluppo di chip ASIC e immissione sul mercato di modelli più produttivi;
  • divulgazione di Bitcoin e afflusso di nuovi minatori;
  • elevato ritorno sugli investimenti nel settore minerario grazie alla rapida crescita del tasso di cambio Bitcoin rispetto al dollaro;
  • trasferimento di potenza di calcolo da altre valute le cui quotazioni scendono o crescono più lentamente di Bitcoin;
  • altri fattori;

La difficoltà di estrazione di Bitcoin è aumentata di 5-6 volte dal 2016. La crescita è continuata quasi ininterrotta. Solo nell’agosto 2017, per la prima volta in un anno, si è registrata una diminuzione dell’indicatore. Forse questo è stato influenzato dal SegWit di Bitcoin di agosto, che ha costretto alcuni miner a trasferire il potere sugli altcoin.

6 risposte

La complessità è sempre specificata in relazione a una variabile specifica o a un insieme di variabili. Quindi, quando lo standard parla di inserimento a tempo costante, stiamo parlando di tempo costante relativo al numero di elementi nell'elenco. Cioè, l'inserimento O(1) significa che il numero di elementi presenti nell'elenco non influisce sulla complessità complessiva degli inserimenti. L'elenco può contenere 500 o 50000000 elementi e la complessità dell'operazione di inserimento sarà la stessa.

Ad esempio, std::list ha O(1) inserimenti ed eliminazioni; il numero di elementi della lista non dipende dalla complessità degli inserimenti. Tuttavia, la complessità dell'allocazione della memoria può dipendere dal numero di cose che sono già state allocate. Ma poiché O(1) parla del numero di elementi nella lista, non lo copre. E questo non è dato per scontato, perché altrimenti misureremmo la complessità dell'allocatore di memoria, non la struttura dei dati.

Insomma: questa è un’altra dimensione.

Ciò significa che possiamo implementare il nostro algoritmo con la forza che vogliamo, incluso uno in cui il tempo non è effettivamente costante in alcun senso pragmatico, ma dove abbiamo rispettato il numero di "operazioni" sugli oggetti contenuti.

La complessità non è specificata rispetto alle implementazioni. È specificato rispetto agli algoritmi. Non importa che il contesto possa cambiare perché il runtime non è un compito difficile.

Come sopra, puoi implementare std::list con un allocatore di memoria che è O(log(n)) rispetto alle eliminazioni (dove n è il numero di allocazioni). Tuttavia, l'eliminazione di un elemento nell'elenco sarà comunque O(1) rispetto al numero di elementi nell'elenco.

Non confondere la complessità con le prestazioni complessive. L’obiettivo della complessità è avere una metrica comune per algoritmi riguardanti variabili diverse. L'obiettivo di un programmatore che desidera che il proprio codice venga eseguito velocemente è trovare un'implementazione ragionevole dell'algoritmo che corrisponda alla complessità richiesta per ottenere tali prestazioni.

La complessità è uno strumento per valutare l’efficacia di un algoritmo. La complessità non significa che puoi smettere di pensare.

Cosa significa esattamente "ammortamento"?

A quanto ho capito, complessità costante significa che l'operazione è O(1): puoi dire in anticipo quante operazioni atomiche (lettura/scrittura, istruzioni di assemblaggio, qualunque cosa) verranno eseguite. E questa stima è un confine comune per tutti i possibili stati dell'oggetto target. C'è un problema qui: in un ambiente multi-thread, non è possibile prevedere gli interruttori di flusso, quindi puoi solo fare qualche ragionamento sul tempo di esecuzione trascorso in un sistema operativo in tempo reale.

Per quanto riguarda la complessità costante ammortizzata, è ancora più debole. Scrivendo un riepilogo delle risposte, ciò garantisce che, in media, la tua operazione sia in corso. Ciò significa che il numero di operazioni elementari per N operazioni successive è O(N) . Ciò significa che il numero di operazioni elementari è circa O(1) ma consente alcuni rari salti. Ad esempio, l'aggiunta di un elemento alla coda di un vettore è solitamente permanente, ma a volte è necessario un ulteriore lavoro pesante; avere un tempo costante ammortizzato significa che l'operazione aggiuntiva non viene eseguita così spesso e richiede una quantità di tempo prevedibile, in modo che il tempo totale dell'operazione N sia ancora O(N) . Naturalmente, lo stesso problema vale anche qui.

Quindi, per rispondere alle tue domande:

  • Le complesse garanzie dello standard si applicano realmente solo al numero di istruzioni del codice macchina necessarie per eseguire un'operazione e non implicano che il tempo di esecuzione sia in alcun modo limitato. (In effetti, fino a poco tempo fa il C++ non aveva nemmeno un puntatore all'argomento correlato al linguaggio, quindi dal punto di vista del C++ standard, ormai il programma veniva eseguito su una macchina C++ specializzata.)
  • L'ammortamento è "mediamente limitato ad una costante", che di solito si verifica nel caso di un tempo di funzionamento limitato quasi sempre costante con alcune deviazioni abbastanza rare.

Modificare:
Puoi guardare, ad esempio, la sezione 23.1 dello standard C++:

Tutti i requisiti di complessità in questa sezione sono specificati esclusivamente in termini di numero di operazioni sugli oggetti contenuti.

quando si dice che un'operazione ha "complessità costante", di solito si riferisce principalmente alla complessità temporale. Potrei riferirmi alla complessità spaziale, ma se così fosse, verrebbe esplicitamente dichiarato normale.

Ora, la complessità di un'operazione si riferisce a quanto tempo aumenterà per completare un'operazione quando aumenta il numero di elementi elaborati nell'operazione. Per un'operazione a complessità costante, la funzione impiegherà la stessa quantità di tempo indipendentemente dal fatto che vengano elaborati zero elementi o dieci milioni di elementi.

    swap() è una complessità costante perché non importa quanti elementi ci sono nel vettore, l'operazione richiederà la stessa quantità di tempo.

    fare clic sull'elenco. è una complessità costante perché sebbene possa essere necessario un certo tempo per allocare un nuovo elemento, questo tempo di allocazione non aumenta perché la lista contiene 10 milioni di elementi (almeno non in senso algoritmico - ovviamente, se la memoria libera diventa più grande e più è esaurita, l'allocazione può richiedere più tempo, ma da un punto di vista algoritmico la quantità di memoria è infinita).

    push_back() su un vettore è chiamata costante "ammortizzata" perché nel caso normale, quando la riallocazione non dovrebbe avvenire, la quantità di tempo impiegata dall'operazione non è correlata al numero di elementi già presenti nel vettore - la stessa quantità di viene impiegato del tempo per aggiungere un nuovo elemento a un vettore di lunghezza zero rispetto a un vettore di lunghezza 10 milioni. Tuttavia, se è necessario riallocare il vettore, sarà necessario avere una copia degli elementi esistenti e questa non è un'operazione costante, ma un'operazione lineare. Ma si suppone che il vettore sia progettato in modo tale che le riallocazioni avvengano raramente, in modo che possano essere ammortizzate su molte operazioni push_back().

ma fare push_back su un vettore è ancora più imprevedibile. Nella maggior parte dei casi questo sarà molto veloce, ma ogni tanto dovrà riallocare lo spazio per tutti i dati e copiare ogni elemento in una nuova posizione. Quindi è meno prevedibile in termini di tempo di esecuzione rispetto al solo list::push_front, ma è comunque chiamato persistente (ammortizzato). In media, l'aggiunta di una grande quantità di dati a un vettore richiederà una complessità indipendente dalla quantità aggiunta, motivo per cui viene chiamato tempo "costante ammortizzato". (Giusto?)

La complessità è O(1) - una costante (tenendo conto della complessità temporale) significa che il tempo di completamento dell'algoritmo non è correlato alla dimensione del problema.

Pertanto, cercare un valore in una struttura con hash è O(1) perché il tempo necessario per farlo è indipendente dal numero dei suoi valori. Tuttavia, lo stesso non vale per una lista concatenata perché dobbiamo scansionare i valori (il cui numero cambia all'aumentare del numero di elementi) per trovare il nostro valore.

Nel caso 3, quando copia ciascun elemento, non è un'operazione O(1), ma un'operazione O(N) (ma la maggior parte delle volte è O(1), quindi di solito è costante). L'ammortamento tiene conto di ciò notando che l'algoritmo in genere viene completato in tempo O(1) e raramente rientra in questo caso O(N).

Probabilmente ti sei imbattuto in notazioni come O(log n) più di una volta o hai sentito frasi come "complessità computazionale logaritmica" indirizzata ad alcuni algoritmi. E se ancora non capisci cosa significa, questo articolo fa per te.

Valutazione della difficoltà

La complessità degli algoritmi viene solitamente misurata dal tempo di esecuzione o dall'utilizzo della memoria. In entrambi i casi, la complessità dipende dalla dimensione dei dati di input: un array di 100 elementi verrà elaborato più velocemente di uno simile di 1000. A pochi però interessa l'ora esatta: dipende dal processore, dal tipo di dati , linguaggio di programmazione e molti altri parametri. È importante solo la complessità asintotica, cioè la complessità quando la dimensione dei dati di input tende all’infinito.

Supponiamo che un algoritmo debba eseguire 4n 3 + 7n operazioni condizionali per elaborare n elementi di dati di input. All'aumentare di n, il tempo operativo finale sarà significativamente più influenzato elevando n a un cubo che moltiplicandolo per 4 o aggiungendo 7n. Quindi dicono che la complessità temporale di questo algoritmo è O(n 3), cioè dipende cubicamente dalla dimensione dei dati di input.

L'uso della O maiuscola (o la cosiddetta notazione O) deriva dalla matematica, dove viene utilizzata per confrontare il comportamento asintotico delle funzioni. Formalmente, O(f(n)) significa che il tempo di esecuzione dell'algoritmo (o la quantità di memoria occupata) cresce in base alla dimensione dei dati di input non più velocemente di una costante moltiplicata per f(n) .

Esempi

O(n) - complessità lineare

Ad esempio, l'algoritmo per trovare l'elemento più grande in un array non ordinato presenta questa complessità. Dovremo esaminare tutti gli n elementi dell'array per capire qual è il massimo.

O(log n) - complessità logaritmica

L'esempio più semplice è la ricerca binaria. Se l'array è ordinato, possiamo verificare se contiene un valore particolare utilizzando il metodo del dimezzamento. Controlliamo l'elemento centrale, se è più grande di quello che stiamo cercando, scarteremo la seconda metà dell'array: sicuramente non è lì. Se è inferiore, viceversa: scarteremo la metà iniziale. E quindi continueremo a dividere a metà e alla fine controlleremo log n elementi.

O(n 2) - complessità quadratica

Ad esempio, l'algoritmo di ordinamento per inserimento ha questa complessità. Nell'implementazione canonica, consiste di due cicli annidati: uno per percorrere l'intero array e il secondo per trovare il posto per l'elemento successivo nella parte già ordinata. Pertanto, il numero di operazioni dipenderà dalla dimensione dell'array come n * n, cioè n 2.

Esistono altri gradi di difficoltà, ma si basano tutti sullo stesso principio.

Accade anche che il tempo di esecuzione dell'algoritmo non dipenda affatto dalla dimensione dei dati di input. Quindi la complessità viene indicata come O(1) . Ad esempio, per determinare il valore del terzo elemento di un array, non è necessario ricordare gli elementi o esaminarli più volte. Devi sempre solo attendere il terzo elemento nel flusso di dati di input e questo sarà il risultato, che impiega lo stesso tempo per calcolare qualsiasi quantità di dati.

Lo stesso vale per le valutazioni della memoria quando questo è importante. Tuttavia, gli algoritmi possono utilizzare molta più memoria quando si aumenta la dimensione dei dati di input rispetto ad altri, ma funzionano comunque più velocemente. E viceversa. Ciò aiuta a scegliere i modi migliori per risolvere i problemi in base alle condizioni e ai requisiti attuali.