A maioria dos trabalhos de programação de baixa latência / alta frequência (com base nas especificações do trabalho) parece estar implementada em plataformas unix. Em muitas das especificações, eles solicitam pessoas com experiência no tipo "linux de baixa latência".
Supondo que isso não signifique um sistema operacional Linux em tempo real, as pessoas poderiam me ajudar com o que isso poderia estar se referindo? Eu sei que você pode definir a afinidade da CPU como threads, mas suponho que eles estejam pedindo muito mais do que isso.
Ajuste do kernel? (embora eu ouvi fabricantes como o solarflare produzirem placas de rede de desvio de kernel)?
E o DMA ou possivelmente a memória compartilhada entre processos? Se as pessoas pudessem me dar breves idéias, posso fazer a pesquisa no google.
(Essa pergunta provavelmente exigirá alguém familiarizado com negociação de alta frequência)
Respostas:
Fiz uma boa quantidade de trabalho apoiando grupos HFT nas configurações do IB e do Hedge Fund. Vou responder da exibição sysadmin, mas parte disso também é aplicável à programação nesses ambientes.
Há algumas coisas que um empregador geralmente procura quando se refere ao suporte "Baixa latência". Algumas delas são perguntas de "velocidade bruta" (você sabe que tipo de cartão de 10g comprar e em que slot o colocar?), Mas mais deles são sobre as maneiras pelas quais um ambiente de negociação de alta frequência difere do tradicional Ambiente Unix. Alguns exemplos:
O Unix é tradicionalmente ajustado para oferecer suporte à execução de um grande número de processos sem precisar de recursos, mas em um ambiente HFT, é provável que você queira executar um aplicativo com um mínimo absoluto de sobrecarga para alternância de contexto e assim por diante. Como um pequeno exemplo clássico, ativar o hyperthreading em uma CPU Intel permite que mais processos sejam executados ao mesmo tempo - mas tem um impacto significativo no desempenho na velocidade em que cada processo individual é executado. Como programador, você também terá que olhar para o custo de abstrações como threading e RPC e descobrir onde uma solução mais monolítica - embora menos limpa - evite sobrecarga.
O TCP / IP geralmente é ajustado para evitar quedas de conexão e fazer uso eficiente da largura de banda disponível. Se seu objetivo é obter a menor latência possível de um link muito rápido - em vez de obter a maior largura de banda possível de um link mais restrito -, convém ajustar o ajuste da pilha de rede. Do lado da programação, você também vai querer examinar as opções de soquete disponíveis e descobrir quais padrões têm mais ajustes para largura de banda e confiabilidade do que para reduzir a latência.
Assim como na rede, no armazenamento - você vai querer saber como diferenciar um problema de desempenho de armazenamento de um problema de aplicativo e aprender quais padrões de uso de E / S têm menor probabilidade de interferir no desempenho do seu programa (como um Por exemplo, saiba onde a complexidade do uso de E / S assíncrona pode render para você e quais são as desvantagens).
Finalmente, e mais dolorosamente: nós, administradores do Unix, queremos o máximo possível de informações sobre o estado dos ambientes que monitoramos, por isso gostamos de executar ferramentas como agentes SNMP, ferramentas de monitoramento ativas como Nagios e ferramentas de coleta de dados como sar (1). Em um ambiente em que as alternâncias de contexto precisam ser absolutamente minimizadas e o uso de E / S de disco e rede seja rigidamente controlado, porém, precisamos encontrar a troca certa entre as despesas de monitoramento e o desempenho bare-metal das caixas monitoradas. Da mesma forma, que técnicas você usa para facilitar a codificação, mas estão custando desempenho?
Finalmente, há outras coisas que vêm com o tempo; truques e detalhes que você aprende com a experiência. Mas eles são mais especializados (quando eu uso o epoll? Por que dois modelos de servidor HP com controladores PCIe teoricamente idênticos têm um desempenho tão diferente?), Mais ligados ao que a sua loja específica está usando e com maior probabilidade de mudar de um ano para outro .
fonte
Além da excelente resposta de ajuste de hardware / configuração do @jimwise, "linux de baixa latência" está implicando:
Muitas dessas técnicas se sobrepõem ao desenvolvimento de jogos, que é uma das razões pelas quais a indústria de software financeiro absorve todos os programadores de jogos recentemente redundantes (pelo menos até que paguem o aluguel atrasado).
A necessidade subjacente é poder ouvir um fluxo muito alto de largura de banda de dados do mercado, como preços de ações (commodities, commodities, câmbio) e, em seguida, tomar uma decisão muito rápida de comprar / vender / não fazer nada com base na segurança, no preço e participações atuais.
Obviamente, tudo isso pode dar errado também.
Então, vou elaborar o ponto das matrizes de bits . Digamos que temos um sistema de negociação de alta frequência que opera em uma longa lista de pedidos (compre 5k IBM, venda 10k DELL etc.). Digamos que precisamos determinar rapidamente se todos os pedidos foram atendidos, para que possamos avançar para a próxima tarefa. Na programação OO tradicional, será semelhante a:
a complexidade algorítmica desse código será O (N), pois é uma varredura linear. Vamos dar uma olhada no perfil de desempenho em termos de acessos à memória: cada iteração do loop dentro de std :: any_of () chamará o.isFilled (), que está embutido, tornando-se um acesso à memória de _isFilled, 1 byte (ou 4, dependendo da sua arquitetura, compilador e configurações do compilador) em um objeto digamos 128 bytes no total. Portanto, estamos acessando 1 byte em cada 128 bytes. Quando lemos o byte de 1 byte, presumindo que seja o pior caso, obteremos uma falha no cache de dados da CPU. Isso fará com que uma solicitação de leitura para a RAM leia uma linha inteira da RAM ( veja aqui para mais informações ) apenas para ler 8 bits. Portanto, o perfil de acesso à memória é proporcional a N.
Compare isso com:
o perfil de acesso à memória disso, assumindo o pior caso novamente, é ELEMS dividido pela largura de uma linha de RAM (varia - pode ser de canal duplo ou triplo, etc.).
Com efeito, estamos otimizando algoritmos para padrões de acesso à memória. Nenhuma quantidade de RAM ajudará - é o tamanho do cache de dados da CPU que causa essa necessidade.
Isso ajuda?
Há uma excelente conversa sobre CPPCon sobre programação de baixa latência (para HFT) no YouTube: https://www.youtube.com/watch?v=NH1Tta7purM
fonte
Como eu não havia colocado um ou dois softwares de alta frequência em produção, diria as coisas mais importantes:
A única pessoa que realmente faz o sistema realizar transações de alta frequência é um cientista da computação que reúne o código em c ++
Entre os conhecimentos utilizados está
A. Operações de comparação e troca.
O cientista talentoso usará mais. Ele deve encontrar nos novos "padrões" recentes um que apareceu primeiro em Java. Chamado padrão DISRUPTOR. A troca de dobras LMAX na Europa explicou à comunidade de alta frequência que a utilização baseada em encadeamento em processadores modernos perderia o tempo de processamento na liberação do cache de memória pela CPU se a fila daya não estiver alinhada com o tamanho do cache da CPU moderna = 64
Portanto, para essa leitura, eles tornaram público um código java que permite que o processo de multiencadeamento use o cache da CPU do hardware corretamente, sem resolução de conflitos. E um bom cientista da computação PRECISA descobrir que esse padrão já foi portado para c ++ ou se portar.
Essa é uma maneira de proficiência além de qualquer configuração de administrador. Isso está no coração real de alta frequência hoje.
E você ficará surpreso ao descobrir que o pipe é usado SOMENTE PARA a notificação do kernel da mensagem que chegou. Você pode colocar o número da mensagem de 64 bits lá - mas para o conteúdo, você acessa a fila CAS sem bloqueio. Disparado por
select()
chamada assíncrona do kernel .Como você pode ver - a alta frequência é um CAMPO DE DESENVOLVIMENTO. Você não pode ser apenas um programador de C ++ para ter sucesso.
E quando digo para ter sucesso, quero dizer que o fundo de hedge para o qual você trabalhará reconhecerá os esforços de turismo em remuneração anual além do número de pessoas e recrutadores que estão falando.
Os tempos das perguntas simples sobre construtores / destruidores desapareceram para sempre. E o c ++ ... migrou com novos compiladores para aliviá-lo do gerenciamento de memória e impor não-herança de grande profundidade nas classes. Perda de tempo. O paradigma de reutilização de código foi alterado. Não se trata apenas de quantas classes você criou em polimorfo. Trata-se de um desempenho em tempo confirmado direto do código que você pode reutilizar.
Portanto, é sua escolha entrar na curva de aprendizado lá, ou não. Ele nunca atingirá um sinal de parada.
fonte