如何提高交易系统的运行速度:C和C++速度优化
Posted 概率量化投资
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何提高交易系统的运行速度:C和C++速度优化相关的知识,希望对你有一定的参考价值。
高频交易系统的核心之一就是速度
天下武功唯快不破,快人一等的速度往往是策略赚钱和不赚钱的关键。程序运行速度的提高是一个系统工程,大致可以分为三个层面:硬件,系统内核和交易程序。这里我们主要从交易程序这个层面来谈谈怎么提高程序的运行速度。
在之前的文章中我们讲了如何通过养成一些好的代码习惯来提高代码的运行速度,对大部分常用的编程语言是有效的。
但是不同的编程语言在系统底层的实现方式各有特色,对不同的编程语言,会有不同的具体优化的方法。在这一期,我们主要介绍一些常用的c,c++的速度优化技巧。C和C++在交易系统中有着大量的应用,速度的优化往往直接与高频策略的盈利挂钩。
1. 尽量使用增量和减量操作符和复合赋值
增量减量和复合赋值操作在cpu计算底层会减少非必要的内存读写,所以在效率上会高一些。
另外,在for loop里index的自加操作,如果没有特殊需求,用++i要比用i++生成的代码效率略高一些。主要是因为++i会少一次赋值操作。
上面的代码测试下来的结果是:
另外,如果loop的方向没有要求的话,由数组尾端向头端反向loop,做--i操作,效率也会快一些。
这段代码运行结果如下:
2. 数据结构体尽量使用struct而非class,尽量少用new
在交易系统中往往会使用一些数据结构来存储数据和交易信息,在选取时,能使用struct的时候尽量避免使用class。使用struct建立的数据结构的内存结构是确定的,所以可以保证所有数据都分配在连续的内存区域。而class可能会产生不确定的内存结构,不利于连续内存分配和操作。
对于结构体,有两个方面要特别注意:首先是把结构体填充成最长类型长度的整倍数,其次是尽量做到数据结构对齐到Cache边界。有关的细节可以参考这篇文章:
"The Lost Art of Structure Packing"
http://www.catb.org/esr/structure-packing/
在计算过程中应该避免使用new, malloc或者calloc动态分配内存。在多线程系统中,系统动态存储分配要求使用锁来控制访问分配器。而且在堆上分配内存,操作系统需要进行一些计算来确定所需大小的内存块。这些都是耗时的操作,对于低延时的高频交易系统,在计算逻辑和循环操作里,要尽量避免。
3. 尽量避免使用虚函数
"一文读懂处理器流水线"
http://m.elecfans.com/article/657563.html
"C++中虚函数(virtual function)到底有多慢"
https://blog.csdn.net/wyq_tc25/article/details/51674698
4. 使用inline函数
内联函数(inline函数)的使用本质上是一种用空间换时间的方法。一般函数的调用时涉及到栈中形参和局部变量的内存分配,传参赋值还有函数跳转等一系列的操作,是比较耗时的。在对速度要求比较高的高频交易中,可以使用内联函数,让编译器在编译代码的时候不将该语句编译成函数调用的指令,而是直接将整个函数体的代码插人调用语句处。这样就减少了执行函数调用的额外开销,但是却增大了执行程序的大小。
5. 使用static函数
如果一个函数只在实现它的文件中被使用,把它声明为static在编译中可以强制自动内联,避免了调用函数时压栈出栈,有助于提高函数调用的速度。
6. 使用noexcept
noexcept是从C++11开始加入的关键字。它告诉编译器,函数中不会发生异常,这有利于编译器对程序做更多的优化。它的使用方法很简单,可以参考:
《深入理解C++11》笔记--noexcept
https://blog.csdn.net/WizardtoH/article/details/80579131
7. 指针运算代替数组索引
通常情况下,在获取数组中的元素时,指针能比数组索引更快。我们可以做一个小测试:
这段代码在gcc普通编译后测试下来,得到的时间是:
8. 利用CPU指令的并行性
现代cpu即便是在单核上也可以同时执行4个浮点数运算、等待4个内存请求。所以我们可以通过循环展开,充分利用cpu的这一性能提高代码运行速度。
这段代码运行的时间是:
可见cpu指令并行对计算性能的提升的帮助还是很明显的。
以上是我们对c,c++程序在代码层面速度优化的一些建议。
如果你有更好的想法,欢迎私信讨论~
以上是关于如何提高交易系统的运行速度:C和C++速度优化的主要内容,如果未能解决你的问题,请参考以下文章