La plupart des travaux de programmation à faible latence / haute fréquence (basés sur les spécifications du travail) semblent être implémentés sur les plates-formes Unix. Dans beaucoup de spécifications, ils font une demande particulière pour les personnes ayant une expérience de type "Linux à faible latence".
En supposant que cela ne signifie pas un système d'exploitation Linux en temps réel, les gens pourraient-ils m'aider à ce à quoi cela pourrait faire référence? Je sais que vous pouvez définir l'affinité CPU pour les threads, mais je suppose qu'ils demandent beaucoup plus que cela.
Réglage du noyau? (même si j'ai entendu des fabricants comme solarflare produire des cartes réseau de contournement du noyau de toute façon)?
Qu'en est-il du DMA ou éventuellement de la mémoire partagée entre les processus? Si les gens pouvaient me donner de brèves idées, je peux aller faire des recherches sur Google.
(Cette question nécessitera probablement une personne familière avec le trading haute fréquence)
Réponses:
J'ai fait pas mal de travail pour soutenir les groupes HFT dans les milieux IB et Hedge Fund. Je vais répondre à partir de la vue sysadmin, mais une partie de cela s'applique également à la programmation dans de tels environnements.
Il y a deux ou trois choses qu'un employeur recherche habituellement lorsqu'il se réfère à un soutien «à faible latence». Certaines d'entre elles sont des questions de "vitesse brute" (savez-vous quel type de carte 10g acheter et dans quel emplacement la mettre?), Mais la plupart concernent les différences entre un environnement de trading à haute fréquence et un environnement traditionnel. Environnement Unix. Quelques exemples:
Unix est traditionnellement réglé pour prendre en charge l'exécution d'un grand nombre de processus sans aucun d'entre eux pour les ressources, mais dans un environnement HFT, vous souhaiterez probablement exécuter une application avec un minimum absolu de surcharge pour le changement de contexte, etc. À titre d'exemple classique, l'activation de l'hyperthreading sur un processeur Intel permet à plus de processus de s'exécuter à la fois - mais a un impact significatif sur les performances de la vitesse à laquelle chaque processus individuel est exécuté. En tant que programmeur, vous devrez également examiner le coût des abstractions telles que le filetage et le RPC, et découvrir où une solution plus monolithique - tout en étant moins propre - évitera les frais généraux.
TCP / IP est généralement réglé pour éviter les interruptions de connexion et utiliser efficacement la bande passante disponible. Si votre objectif est d'obtenir la latence la plus faible possible d'une liaison très rapide - au lieu d'obtenir la bande passante la plus élevée possible d'une liaison plus contrainte - vous allez vouloir ajuster le réglage de la pile réseau. Du côté de la programmation, vous souhaiterez également examiner les options de socket disponibles et déterminer celles dont les paramètres par défaut sont plus adaptés à la bande passante et à la fiabilité qu'à la réduction de la latence.
Comme pour la mise en réseau, donc pour le stockage - vous allez vouloir savoir comment distinguer un problème de performances de stockage d'un problème d'application et apprendre quels modèles d'utilisation des E / S sont les moins susceptibles d'interférer avec les performances de votre programme (en tant que par exemple, découvrez où la complexité de l'utilisation d'E / S asynchrones peut vous rapporter et quels sont les inconvénients).
Enfin, et plus douloureusement: nous, les administrateurs Unix, voulons autant d' informations que possible sur l'état des environnements que nous surveillons, nous aimons donc exécuter des outils comme les agents SNMP, des outils de surveillance actifs comme Nagios et des outils de collecte de données comme sar (1). Dans un environnement où les changements de contexte doivent être absolument minimisés et l'utilisation des E / S disque et réseau étroitement contrôlée, nous devons cependant trouver le bon compromis entre les frais de surveillance et les performances nues des boîtiers surveillés. De même, quelles techniques utilisez-vous qui facilitent le codage mais vous coûtent les performances?
Enfin, il y a d'autres choses qui viennent avec le temps; astuces et détails que vous apprenez avec l'expérience. Mais ceux-ci sont plus spécialisés (quand dois-je utiliser epoll? Pourquoi deux modèles de serveur HP avec des contrôleurs PCIe théoriquement identiques fonctionnent-ils si différemment?), Plus liés à ce que votre magasin spécifique utilise, et plus susceptibles de changer d'une année à l'autre .
la source
En plus de l'excellente réponse de réglage matériel / configuration de @jimwise, "Linux à faible latence" implique:
Beaucoup de ces techniques se chevauchent avec le développement de jeux, ce qui est l'une des raisons pour lesquelles l'industrie des logiciels financiers absorbe les programmeurs de jeux récemment redondants (au moins jusqu'à ce qu'ils paient leurs arriérés de loyer).
Le besoin sous-jacent est de pouvoir écouter un flux de données de marché très large bande passante telles que les prix des titres (actions, matières premières, fx), puis de prendre une décision d'achat / vente / de ne rien faire très rapide en fonction de la sécurité, du prix et les avoirs actuels.
Bien sûr, tout cela peut aussi mal tourner de façon spectaculaire .
Je vais donc développer le point des tableaux de bits . Disons que nous avons un système de trading à haute fréquence qui fonctionne sur une longue liste d'ordres (acheter 5k IBM, vendre 10k DELL, etc.). Disons que nous devons déterminer rapidement si toutes les commandes sont remplies, afin de pouvoir passer à la tâche suivante. Dans la programmation OO traditionnelle, cela ressemblera à ceci:
la complexité algorithmique de ce code va être O (N) car c'est un balayage linéaire. Jetons un coup d'œil au profil de performance en termes d'accès à la mémoire: chaque itération de la boucle à l'intérieur de std :: any_of () va appeler o.isFilled (), qui est en ligne, devient ainsi un accès à la mémoire de _isFilled, 1 octet (ou 4 selon votre architecture, le compilateur et les paramètres du compilateur) dans un objet de disons 128 octets au total. Nous accédons donc à 1 octet sur 128 octets. Lorsque nous lisons le 1 octet, en supposant le pire des cas, nous obtiendrons un cache de données CPU manquant. Cela provoquera une demande de lecture vers la RAM qui lit une ligne entière de la RAM ( voir ici pour plus d'informations ) juste pour lire 8 bits. Le profil d'accès à la mémoire est donc proportionnel à N.
Comparez cela avec:
le profil d'accès à la mémoire de celui-ci, en supposant à nouveau le pire des cas, est ELEMS divisé par la largeur d'une ligne RAM (varie - pourrait être double canal ou triple canal, etc.).
Donc, en fait, nous optimisons les algorithmes pour les modèles d'accès à la mémoire. Aucune quantité de RAM ne sera utile - c'est la taille du cache de données CPU qui provoque ce besoin.
est-ce que cela aide?
Il y a un excellent CPPCon parler de la programmation à faible latence (pour HFT) sur YouTube: https://www.youtube.com/watch?v=NH1Tta7purM
la source
Comme je n'avais pas mis en production un ou deux logiciels haute fréquence, je dirais les choses les plus importantes:
La seule personne qui fabrique réellement le système pour faire du trading haute fréquence est un informaticien qui assemble le code en c ++
Parmi les connaissances utilisées figure
A. Comparer et échanger des opérations.
Le scientifique talentueux en utilisera davantage. Il devrait en trouver dans les nouveaux "patterns" récents qui sont apparus en premier en Java. Appelé motif DISRUPTOR. Un échange LMAX en Europe a expliqué à la communauté haute fréquence que l'utilisation basée sur les threads dans les processeurs modernes perdrait du temps de traitement sur la libération du cache mémoire par le CPU si la file d'attente daya n'était pas alignée avec la taille du cache cpu moderne = 64
Donc, pour cette lecture, ils ont rendu public un code java qui permet au processus multithread d'utiliser correctement le cache du processeur matériel sans résolution de conflits. Et un bon informaticien DOIT trouver que ce modèle a déjà été porté en c ++ ou le faire lui-même.
Il s'agit d'un moyen de compétence au-delà de toute configuration d'administration. C'est en vrai coeur de haute fréquence aujourd'hui.
Et vous serez étonné de constater que le canal est utilisé UNIQUEMENT POUR la notification par le noyau du message arrivé. Vous pouvez y mettre le numéro de message 64 bits - mais pour le contenu, vous accédez à votre file d'attente CAS sans verrouillage. Déclenché par un
select()
appel de noyau asynchrone .Comme vous pouvez le voir - la haute fréquence est un CHAMP EN DÉVELOPPEMENT. Vous ne pouvez pas être un simple programmeur C ++ pour réussir.
Et quand je dis pour réussir, je veux dire que le hedge fund pour lequel vous travaillerez reconnaîtra les efforts de tournée en compensation annuelle au-delà des chiffres dont parlent les gens et les recruteurs.
L'époque de la simple FAQ constructeur / destructeur est révolue pour toujours. Et c ++… lui-même a migré avec de nouveaux compilateurs pour vous soulager de la gestion de la mémoire et pour imposer le non-héritage de grande profondeur dans les classes. Perte de temps. Le paradigme de réutilisation du code a changé. Il ne s'agit pas seulement du nombre de classes que vous avez créées en polymorphe. Il s'agit de performances temporelles confirmées directement du code que vous pouvez réutiliser.
C'est donc votre choix de vous lancer dans la courbe d'apprentissage, ou non. Il ne frappera jamais un panneau d'arrêt.
la source