Unix / Linux a bassa latenza

11

La maggior parte dei lavori di programmazione a bassa latenza / alta frequenza (in base alle specifiche del lavoro) sembra essere implementata su piattaforme unix. In molte specifiche fanno richieste particolari per le persone con esperienza di tipo "bassa latenza linux".

Supponendo che questo non significhi un sistema operativo Linux in tempo reale, le persone potrebbero darmi aiuto con ciò a cui questo potrebbe riferirsi? So che puoi impostare l'affinità della CPU con i thread, ma presumo che chiedano molto di più rispetto a questo.

Ottimizzazione del kernel? (anche se ho sentito produttori come Solarflare produrre comunque schede di rete bypass del kernel)?

Che dire di DMA o forse di memoria condivisa tra processi? Se le persone potessero darmi brevi idee, posso andare a fare ricerche su google.

(Questa domanda richiederà probabilmente qualcuno che abbia familiarità con il trading ad alta frequenza)

    
posta user997112 15.01.2013 - 21:40
fonte

3 risposte

24

Ho svolto una discreta attività di supporto ai gruppi HFT nelle impostazioni IB e Hedge Fund. Ho intenzione di rispondere dalla visualizzazione sysadmin, ma alcuni di questi sono applicabili anche alla programmazione in tali ambienti.

Ci sono un paio di cose che un datore di lavoro di solito cerca quando si riferiscono al supporto "Bassa latenza". Alcune di queste sono domande a "velocità grezza" (sai che tipo di scheda da 10g comprare e quale slot inserire?), Ma molte di queste riguardano i modi in cui un ambiente di trading ad alta frequenza si differenzia da un tradizionale Ambiente Unix. Alcuni esempi:

  • Unix è tradizionalmente ottimizzato per supportare l'esecuzione di un gran numero di processi senza affamare nessuno di essi per le risorse, ma in un ambiente HFT, è probabile che vogliate eseguire un'applicazione una con un minimo assoluto di spese generali per il cambio di contesto e così via. Come classico esempio, l'attivazione dell'hyperthreading su una CPU Intel consente l'esecuzione di più processi contemporaneamente, ma ha un impatto significativo sulle prestazioni della velocità con cui viene eseguito ciascun singolo processo. Come programmatore, dovrai analizzare il costo delle astrazioni come threading e RPC, e capire dove una soluzione più monolitica - mentre meno pulita - eviterà il sovraccarico.

  • TCP / IP è in genere sintonizzato per impedire le interruzioni della connessione e sfruttare in modo efficiente la larghezza di banda disponibile. Se il tuo obiettivo è ottenere la latenza più bassa possibile da un collegamento molto veloce - invece di ottenere la massima larghezza di banda possibile da un link più limitato - tu intenzione di voler regolare la messa a punto dello stack di rete. Da un punto di vista della programmazione, vorrai anche esaminare le opzioni di socket disponibili e capire quali sono i valori predefiniti più ottimizzati per larghezza di banda e affidabilità rispetto a quelli per ridurre la latenza.

  • Come con il networking, quindi con lo storage, vorrai sapere come distinguere un problema di prestazioni dello storage da un problema applicativo e imparare quali pattern di utilizzo I / O hanno meno probabilità di interferire con le prestazioni del tuo programma (ad esempio, scopri dove la complessità dell'uso dell'IO asincrono può ripagarti, e quali sono i lati negativi).

  • Infine, e più dolorosamente: noi amministratori di Unix vogliamo come molte informazioni sullo stato degli ambienti che monitoriamo il più possibile, quindi ci piace eseguire strumenti come agenti SNMP, strumenti di monitoraggio attivi come Nagios e strumenti di raccolta dati come sar (1). In un ambiente in cui gli switch di contesto devono essere assolutamente minimizzati e l'utilizzo di IO del disco e della rete strettamente controllato, tuttavia, dobbiamo trovare il giusto compromesso tra le spese di monitoraggio e le prestazioni bare metal delle scatole monitorate. Allo stesso modo, quali tecniche stai usando che rendono la codifica più semplice ma ti stanno costando delle prestazioni?

Infine, ci sono altre cose che vengono con il tempo; trucchi e dettagli che impari con l'esperienza. Ma questi sono più specializzati (quando uso epoll? Perché due modelli di server HP con controller PCIe teoricamente identici funzionano in modo così diverso?), Più legati a qualsiasi negozio specifico e più probabilità di passare da un anno all'altro .

    
risposta data 15.01.2013 - 22:15
fonte
14

Oltre all'eccellente risposta all'ottimizzazione hardware / setup di @jimwise, "linux a bassa latenza" sta implicando:

  • C ++ per ragioni di determinismo (nessun ritardo a sorpresa mentre GC entra in gioco), accesso a strutture di basso livello (I / O, segnali), potenza della lingua (pieno utilizzo di TMP e STL, sicurezza di tipo).
  • preferisci la velocità di memoria: > 512 Gb di RAM sono comuni; i database sono in-memory, cache nascoste o esotici prodotti NoSQL.
  • Scelta dell'algoritmo
  • : il più veloce possibile rispetto a sano / comprensibile / estensibile, ad es. array di bit multipli senza blocco anziché proprietà array-of-objects-with-bool.
  • pieno utilizzo delle funzionalità del sistema operativo come la memoria condivisa tra processi su diversi core.
  • sicuro. Il software HFT è solitamente collocato in una borsa valori, pertanto le possibilità di malware sono inaccettabili.

Molte di queste tecniche si sono sovrapposte allo sviluppo dei giochi e questo è uno dei motivi per cui il settore del software finanziario assorbe programmatori di giochi ridondanti di recente (almeno fino a quando non pagano gli arretrati).

L'esigenza di fondo è quella di essere in grado di ascoltare un flusso molto elevato di dati di mercato come la sicurezza (scorte, materie prime, fx) e quindi prendere una decisione di acquisto / vendita / rinunciare molto veloce basata sulla sicurezza , il prezzo e le disponibilità attuali.

Naturalmente, tutto questo può andare in modo spettacolare sbagliato , anche.

Quindi elaborerò il punto matrici bit . Diciamo che abbiamo un sistema di trading ad alta frequenza che opera su una lunga lista di ordini (Acquista 5k IBM, Vendi 10k DELL, ecc.). Diciamo che dobbiamo determinare rapidamente se tutti gli ordini sono stati completati, in modo che possiamo passare all'attività successiva. Nella programmazione OO tradizionale, questo assomiglierà a:

class Order {
  bool _isFilled;
  ...
public:
  inline bool isFilled() const { return _isFilled; }
};

std::vector<Order> orders;
bool needToFillMore = std::any_of(orders.begin(), orders.end(), 
  [](const Order & o) { return !o.isFilled(); } );

la complessità algoritmica di questo codice sarà O (N) in quanto è una scansione lineare. Diamo un'occhiata al profilo delle prestazioni in termini di accessi alla memoria: ogni iterazione del ciclo all'interno di std :: any_of () chiamerà o.isFilled (), che è in linea, quindi diventa un accesso alla memoria di _isFilled, 1 byte (o 4 a seconda dell'architettura, del compilatore e delle impostazioni del compilatore) in un oggetto di diciamo 128 byte totali. Quindi stiamo accedendo a 1 byte ogni 128 byte. Quando leggiamo l'1 byte, presumendo il caso peggiore, avremo una perdita della cache dei dati della CPU. Ciò causerà una richiesta di lettura alla RAM che legge un'intera riga dalla RAM ( vedi qui per maggiori informazioni ) solo leggere 8 bit. Quindi il profilo di accesso alla memoria è proporzionale a N.

Confronta questo con:

const size_t ELEMS = MAX_ORDERS / sizeof (int);
unsigned int ordersFilled[ELEMS];

bool needToFillMore = std::any_of(ordersFilled, &ordersFilled[ELEMS+1],
   [](int packedFilledOrders) { return !(packedOrders == 0xFFFFFFFF); }

il profilo di accesso alla memoria di questo, assumendo di nuovo il caso peggiore, è ELEMS diviso per la larghezza di una linea RAM (varia - potrebbe essere doppio canale o triplo canale, ecc.)

Quindi, in effetti, stiamo ottimizzando gli algoritmi per i modelli di accesso alla memoria. Nessuna quantità di RAM aiuterà - è la dimensione della cache dei dati della CPU che causa questa necessità.

Questo aiuto?

C'è un CPPCon eccellente che parla di programmazione a bassa latenza (per HFT) su YouTube: link

    
risposta data 16.01.2013 - 15:38
fonte
-2

Poiché non avevo messo in produzione uno o due software ad alta frequenza, direi le cose più importanti:

  1. La configurazione hardware e gli amministratori di sistema insieme ai tecnici di rete NON definiscono un buon risultato del numero di ordini elaborati dal sistema di trading, ma possono ridimensionarlo in modo significativo se non conoscono le nozioni di base sopra delineate.
  2. L'unica persona che effettivamente fa il sistema per fare trading ad alta frequenza è uno scienziato informatico che mette insieme il codice in c ++

    Tra le conoscenze utilizzate

    A. Confronta e scambia le operazioni.

    • come il CAS viene utilizzato nel processore e come il computer lo supporta per essere utilizzato nell'elaborazione della struttura No-Locking. Oppure elaborazione senza blocco. Non andrò a scrivere un intero libro qui. In breve, il compilatore GNU e il compilatore Microsoft supportano l'uso diretto delle istruzioni CAS. Permette al tuo codice di avere "No.Wair" mentre estrae l'elemento dalla coda o ne inserisce uno nuovo nella coda.
  3. Il talentuoso scienziato userà di più. Dovrebbe trovare in recenti nuovi "modelli" uno che è apparso in Java prima. Chiamato modello DISRUPTOR. Piegare lo scambio LMAX in Europa ha spiegato alla comunità ad alta frequenza che l'utilizzo basato su thread nei processori moderni avrebbe perso tempo di elaborazione sul rilascio della cache di memoria da parte della CPU se la coda del giorno non è allineata con la dimensione della cache cpu moderna = 64

    Quindi per quel readon hanno reso pubblico un codice java che consente al processo multi-threading di utilizzare correttamente la cache della CPU dell'hardware senza risoluzioni di conflitto. E un bravo scienziato informatico deve scoprire che il modello è già stato convertito in c ++ o che si sta facendo il porting.

    Questo è un modo molto più efficace di qualsiasi configurazione di amministrazione. Questo è nel vero cuore delle alte frequenze oggi.

  4. L'uomo di informatica deve scrivere molto codice C ++ non solo per aiutare le persone del QA. Ma anche
    • convalidare nei trader faccia la comprovata velocità raggiunta
    • condanna usato diverse vecchie tecnologie e le espone con il proprio codice per dimostrare che non riesce a produrre buoni risultati
    • scrivi il proprio codice c ++ di comunicazione multi-threading basato su pupe comprovate / seleziona la velocità del kernel invece di utilizzare nuovamente le vecchie tecnologie. Ti darò un esempio: la moderna libreria Tcp è ICE. E la gente che lo ha fatto è brillante. Ma le loro priorità erano nel campo della compatibilità con molte lingue. Così. Puoi fare di meglio in c ++. Quindi cerca i migliori risultati in termini di prestazioni in base alla chiamata selettiva ASYNCHRONOUS. E non andare per più consumatori più produttori - non per HF.
      E sarai sorpreso di scoprire che la pipe viene utilizzata SOLO PER la notifica del kernel del messaggio arrivato. È possibile inserire il numero di messaggio a 64 bit lì - ma per il contenuto si passa alla coda CAS senza blocco. Attivato dal kernel asincrono% chiamata% ch_de.
    • inoltre. Ulteriori informazioni sull'assegnazione dell'affinità del thread c ++ al thread che esegue il piping / l'accodamento dei messaggi. Quel thread dovrebbe avere affinità core. Nessun altro dovrebbe usare lo stesso numero di core della CPU.
    • e così via.

Come puoi vedere, l'alta frequenza è un CAMPO SVILUPPO. Non puoi essere solo un programmatore C ++ per avere successo.

E quando dico per avere successo intendo che l'hedge fund per cui lavorerai WILL riconoscerà gli sforzi del tour in compensi annuali oltre il numero di persone e reclutatori che parlano.

I tempi delle semplici FAQ del costruttore / distruttore sono finiti per sempre. e c ++ ... stesso è stato migrato con nuovi compilatori per alleggerirti dalla gestione della memoria e per imporre l'assenza di ereditarietà di una grande profondità nelle classi. Perdita di tempo. Il paradigma del riutilizzo del codice è cambiato. Non si tratta solo di quante lezioni hai fatto in polimorfo. Si tratta di prestazioni temporali confermate dirette di codice che è possibile riutilizzare.

Quindi è una tua scelta entrare in una curva di apprendimento, oppure no. Non colpirà mai un segnale di stop.

    
risposta data 03.09.2017 - 21:28
fonte

Leggi altre domande sui tag