@jimwise의 뛰어난 하드웨어 / 설정 튜닝 답변 외에도 "낮은 대기 시간 Linux"는 다음을 의미합니다.
- 결정 성 (GC가 시작되는 동안 놀라운 지연이 없음), 저수준 시설 (I / O, 신호)에 대한 액세스, 언어 능력 (TMP 및 STL의 완전한 사용, 유형 안전)을 이유로 C ++.
- 메모리 초과 속도 선호 :> 512Gb 이상의 RAM이 일반적입니다. 데이터베이스는 인 메모리, 캐시 된 선행 또는 이국적인 NoSQL 제품입니다.
- 알고리즘 선택 : 가능한 빠른 객체 대 제곱 / 이해 가능한 / 확장 가능 (예 : 잠금없는 객체 비트 속성 대신 잠금없는 다중 비트 어레이)
- 다른 코어의 프로세스 간 공유 메모리와 같은 OS 기능을 완벽하게 사용합니다.
- 안전한. HFT 소프트웨어는 일반적으로 증권 거래소에 함께 위치하므로 맬웨어 가능성은 용납 할 수 없습니다.
이러한 기술 중 다수는 게임 개발과 겹치며, 이는 금융 소프트웨어 산업이 최근에 중복 된 게임 프로그래머를 흡수하는 이유 중 하나입니다 (최소한 임대료를 지불 할 때까지).
기본 요구 사항은 보안 (주식, 상품, FX) 가격과 같은 매우 높은 대역폭의 시장 데이터를 수신 한 다음 보안, 가격을 기반으로 매우 빠른 구매 / 판매 / 무 결정 결정을 내릴 수 있어야합니다. 그리고 현재 보유.
물론, 이것 역시 훌륭하게 잘못 될 수 있습니다.
비트 배열 포인트를 자세히 설명하겠습니다 . 긴 주문 목록 (5k IBM 구매, 10k DELL 판매 등)으로 운영되는 고주파 거래 시스템이 있다고 가정 해 봅시다. 다음 작업으로 넘어갈 수 있도록 모든 주문이 채워 졌는지 신속하게 결정해야한다고 가정 해 봅시다. 전통적인 OO 프로그래밍에서는 다음과 같습니다.
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(); } );
이 코드의 알고리즘 복잡도는 선형 스캔이므로 O (N)이됩니다. 메모리 액세스 측면에서 성능 프로파일을 살펴 보겠습니다. std :: any_of () 내부 루프의 각 반복은 인라인 된 o.isFilled ()를 호출하므로 _isFilled, 1 바이트의 메모리 액세스가됩니다. (또는 4는 아키텍처, 컴파일러 및 컴파일러 설정에 따라 다름) 총 128 바이트라고하는 객체입니다. 따라서 128 바이트마다 1 바이트에 액세스하고 있습니다. 최악의 경우를 가정하여 1 바이트를 읽으면 CPU 데이터 캐시 미스가 발생합니다. 이로 인해 RAM에 대한 읽기 요청이 발생하여 RAM에서 전체 라인을 읽습니다 ( 자세한 내용은 여기 참조 ). 따라서 메모리 액세스 프로파일은 N에 비례합니다.
이것을 다음과 비교하십시오.
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); }
최악의 경우를 가정하면, 이것의 메모리 액세스 프로파일은 ELEMS를 RAM 라인의 너비로 나눈 값입니다 (다양-이중 채널 또는 3 중 채널 등일 수 있음).
실제로 메모리 액세스 패턴에 대한 알고리즘을 최적화하고 있습니다. 많은 양의 RAM이 도움이되지 않습니다. 이것이 필요한 CPU 데이터 캐시 크기입니다.
도움이 되나요?
YouTube의 저 지연 프로그래밍 (HFT 용)에 대한 훌륭한 CPPCon 강연이 있습니다 : https://www.youtube.com/watch?v=NH1Tta7purM