最近帮一个做量化朋友调他的多币种回测环境,发现他i9-13900K跑8个货币对并行测试,CPU利用率才30%出头,当时就觉得这个现象值得拿出来聊聊。很多人以为MT5策略测试器开了多币种并行就是自动吃满所有核心,其实完全不是这么回事,核心分配的逻辑比想象中要绕。
先说结论,MT5的并行回测并不是每个货币对独立占一个核心那么简单。实际上它的调度机制是
我踩过的坑是这样的,一开始我直接在“设置-策略测试器-并行”里拉满所有核心,结果反而比默认设置还慢。后来用任务管理器盯了一下,发现MT5主进程和回测进程的亲和性设置有问题。解决办法是在启动回测前,用PowerShell手动设置进程亲和性,把MT5主程序绑在偶数核心,回测worker绑在奇数核心,这样能避免两个进程抢同一个物理核的L2缓存。
具体操作步骤我整理一下:
还有个容易被忽略的点,如果你用云服务器跑回测,特别是那种共享CPU的VPS,一定要先跑一下`Get-CimInstance Win32_Processor | Select-Object NumberOfCores,NumberOfLogicalProcessors`确认物理核数。我之前在一台号称8核的VPS上跑,结果查出来只有4物理核8线程,MT5却按8逻辑核心去分配,导致两个worker挤在同一个物理核上,回测速度反而比单币种还慢。
另外提一下,如果你同时跑EURUSD、GBPUSD、USDJPY这种相关性高的品种,建议把tick数据源分开存放。默认都在history文件夹里,并发读取时会有锁竞争。我是把三个品种的history文件分别复制到不同目录,然后在测试器里手动指定数据源路径,速度提升大概有15%左右。
最后想问问大家,有没有试过在MT5的Agent模式下用Docker容器隔离每个货币对的回测环境?我最近在折腾这个,感觉比手动设置亲和性更干净,但Agent的负载均衡好像不太智能,想听听有没有更好的调度方案。
先说结论,MT5的并行回测并不是每个货币对独立占一个核心那么简单。实际上它的调度机制是
- 每个回测任务默认占用2个逻辑核心(一个跑tick流,一个跑策略计算)
- 如果勾选了“优化”模式,每个参数组合会再额外抢占核心
我踩过的坑是这样的,一开始我直接在“设置-策略测试器-并行”里拉满所有核心,结果反而比默认设置还慢。后来用任务管理器盯了一下,发现MT5主进程和回测进程的亲和性设置有问题。解决办法是在启动回测前,用PowerShell手动设置进程亲和性,把MT5主程序绑在偶数核心,回测worker绑在奇数核心,这样能避免两个进程抢同一个物理核的L2缓存。
具体操作步骤我整理一下:
- 第一步,打开MT5安装目录,找到terminal64.exe,右键属性-兼容性-勾选“禁用全屏优化”
- 第二步,在回测前用这个命令设置亲和性:`powershell "Get-Process terminal64 | Select-Object -ExpandProperty Id | ForEach-Object { $cpu = 0,2,4,6,8,10,12,14; $_ | Set-ProcessAffinity $cpu }"`
- 第三步,MT5设置里把“测试器最大线程数”改为物理核心数减2,比如8核16线程就填6
- 第四步,每个货币对单独建一个测试文件,不要用“全部品种”选项,这样能避免IO瓶颈
还有个容易被忽略的点,如果你用云服务器跑回测,特别是那种共享CPU的VPS,一定要先跑一下`Get-CimInstance Win32_Processor | Select-Object NumberOfCores,NumberOfLogicalProcessors`确认物理核数。我之前在一台号称8核的VPS上跑,结果查出来只有4物理核8线程,MT5却按8逻辑核心去分配,导致两个worker挤在同一个物理核上,回测速度反而比单币种还慢。
另外提一下,如果你同时跑EURUSD、GBPUSD、USDJPY这种相关性高的品种,建议把tick数据源分开存放。默认都在history文件夹里,并发读取时会有锁竞争。我是把三个品种的history文件分别复制到不同目录,然后在测试器里手动指定数据源路径,速度提升大概有15%左右。
最后想问问大家,有没有试过在MT5的Agent模式下用Docker容器隔离每个货币对的回测环境?我最近在折腾这个,感觉比手动设置亲和性更干净,但Agent的负载均衡好像不太智能,想听听有没有更好的调度方案。
