第二章:硬件基础与选型
做量化交易系统,说白了就是跟硬件打交道。你算法再牛,代码再优雅,底层硬件跟不上,一切都是白搭。我见过太多团队,花大价钱买服务器,结果性能瓶颈出在CPU架构上,你说冤不冤?
这一章,咱们聊聊硬件选型那些事儿。我会结合自己踩过的坑,给你讲讲CPU、内存、网卡、SSD到底该怎么选。
2.1 CPU架构:NUMA vs SMP
先问个问题:你知不知道你的CPU是怎么访问内存的?
传统SMP架构,所有CPU核心共享一条内存总线。好处是编程简单,坏处是——核心一多,总线就堵车。我早年做高频交易系统时,用的就是SMP服务器,8个核心跑满后,内存延迟直接翻倍。那感觉,就像早高峰的北京三环。
NUMA架构就不一样了。每个CPU有自己的本地内存,访问本地内存快,访问远端内存慢。嗯,这里要注意:NUMA下,内存访问延迟差异可能达到2-3倍。
核心结论:量化交易系统,尤其是高频交易场景,必须用NUMA架构。SMP只适合核心数少于8的场景。
我个人习惯,在NUMA机器上做性能调优时,第一件事就是绑核。把交易线程绑定到指定CPU核心,同时把内存分配在本地节点。怎么做?
# 查看NUMA拓扑
numactl --hardware
# 将进程绑定到node0的CPU核心0-3
numactl --cpunodebind=0 --membind=0 ./trading_engine
# 运行时动态绑定线程
taskset -c 0-3 ./trading_engine
我曾经遇到过一个坑:某次上线新策略,发现延迟抖动特别大。查了半天,原来是操作系统把线程迁移到了另一个NUMA节点。从那以后,我所有生产环境都强制绑核。
2.2 内存层级:L1/L2/L3缓存
内存层级这事儿,很多做软件的人容易忽略。你想想看,CPU主频已经到5GHz了,但内存访问延迟还在100ns级别。这中间的差距,全靠缓存来填。
| 缓存层级 | 典型大小 | 访问延迟 | 带宽 |
|---|---|---|---|
| L1 | 32KB | ~1ns | ~1TB/s |
| L2 | 256KB | ~4ns | ~500GB/s |
| L3 | 8-32MB | ~15ns | ~200GB/s |
| 主存 | 64GB+ | ~100ns | ~50GB/s |
看到没?L1缓存比主存快100倍。所以,量化交易系统的核心数据结构,必须想办法塞进L1缓存。
我建议,订单簿、行情快照这些高频访问的数据,大小控制在32KB以内。怎么做到?用紧凑的数据结构,别用std::map这种重量级容器。我项目中常用的是自定义的数组+指针池,配合cache line对齐。
// 缓存行对齐示例
struct alignas(64) Order {
int64_t price;
int64_t volume;
uint32_t order_id;
// 填充到64字节
char padding[64 - sizeof(int64_t)*2 - sizeof(uint32_t)];
};
static_assert(sizeof(Order) == 64, "Order must be 64 bytes");
为什么对齐到64字节?因为现代CPU的缓存行就是64字节。不对齐的话,一个结构体可能跨两个缓存行,访问一次要读两次内存,性能直接腰斩。
避坑指南:我曾经在项目中用了一个std::vector来存订单,结果发现每次遍历都会触发大量缓存未命中。换成自定义的环形缓冲区后,延迟降低了40%。
2.3 网卡选型:Solarflare vs Mellanox
网卡是量化交易系统的咽喉。普通网卡延迟在10-20微秒,而专用网卡可以做到1微秒以内。差距有多大?一个订单从生成到成交,可能就差这十几微秒。
目前主流的高频交易网卡就两家:Solarflare和Mellanox。
| 特性 | Solarflare | Mellanox |
|---|---|---|
| 延迟 | ~1μs | ~1.5μs |
| 用户态驱动 | OpenOnload | RDMA/DPDK |
| 硬件时间戳 | 支持 | 支持 |
| 价格 | 较高 | 中等 |
| 生态 | 金融行业标准 | HPC/云原生 |
我个人更倾向Solarflare。为什么?因为OpenOnload这个用户态协议栈太成熟了。你不需要改任何代码,直接LD_PRELOAD就能把TCP延迟从10μs降到1μs。我当年第一次用的时候,简直不敢相信——就这么简单?
但要注意,Solarflare的驱动对内核版本有要求。我曾经在CentOS 7.9上折腾了三天,才把OpenOnload跑起来。嗯,这里建议直接用官方推荐的OS版本。
# 使用OpenOnload加速应用
LD_PRELOAD=libonload.so ./trading_engine
# 查看网卡硬件时间戳
ethtool -T eth0
Mellanox的优势在于RDMA。如果你做的是跨机房低延迟传输,RDMA是唯一选择。但RDMA编程复杂度高,需要改应用层代码。
警告:别以为买了高端网卡就万事大吉。网卡驱动、BIOS设置、PCIe插槽位置,任何一个环节没优化好,延迟都会翻倍。我见过有人把网卡插在PCIe x8槽上,结果带宽只有x16的一半。
2.4 SSD选型:NVMe vs SATA
SSD这块,很多人觉得随便买一块就行。但量化交易系统对存储的要求很特殊——不是看顺序读写,而是看随机读写和延迟一致性。
普通SATA SSD,随机读写延迟在100-200微秒。NVMe SSD可以做到10-20微秒。差距10倍。而且,NVMe的队列深度是SATA的几十倍,并发能力完全不在一个量级。
| 指标 | SATA SSD | NVMe SSD | Intel Optane |
|---|---|---|---|
| 接口 | SATA 3.0 | PCIe 3.0/4.0 | PCIe 3.0 |
| 顺序读 | ~550MB/s | ~3500MB/s | ~2400MB/s |
| 随机读(4K) | ~90K IOPS | ~500K IOPS | ~2.5M IOPS |
| 延迟 | ~100μs | ~20μs | ~10μs |
| 价格 | 低 | 中 | 高 |
我建议,交易系统的日志和行情数据,用NVMe SSD。历史回测数据,可以用SATA SSD。至于Intel Optane,虽然延迟低得离谱,但价格也离谱,除非你预算无上限,否则不推荐。
这里有个细节:SSD的写入寿命。量化交易系统每秒可能产生几千条日志,一天下来就是几GB。普通TLC SSD可能一年就写废了。我习惯用企业级NVMe SSD,比如三星PM9A3或铠侠CD6系列,写入寿命是消费级的10倍。
# 查看SSD写入量
smartctl -a /dev/nvme0 | grep "Data Units Written"
# 优化SSD性能(关闭写缓存)
nvme set-feature /dev/nvme0 -f 0x06 -v 0
避坑指南:我曾经贪便宜买了消费级SSD做行情存储,结果三个月后IOPS掉了一半。后来换成企业级NVMe,再也没出过问题。记住,交易系统里,稳定比便宜重要100倍。
2.5 知识体系总览
说了这么多,咱们用一张图来总结本章的核心逻辑。这张图展示了硬件选型与性能调优的完整链路:
这张图把CPU、内存、网卡、SSD串起来了。你会发现,每一层都在为降低延迟服务。从CPU绑核到缓存对齐,从用户态网卡到NVMe SSD,环环相扣。
好了,硬件选型就聊到这儿。记住一句话:量化交易系统的性能,不是靠某一个组件,而是靠整个链路。你CPU再快,网卡延迟高也没用;你网卡再好,SSD写入慢也白搭。