Car*_*los 31 .net c++ performance finance real-time
我认为C/C++与C#/ Java性能问题很好,这意味着我已经阅读了足够的证据来证明VM语言不一定比"接近硅"语言慢.主要是因为JIT编译器可以进行静态编译语言无法进行的优化.
然而,我最近收到了一个人的简历,他声称基于Java的高频交易总是被C++击败,并且他一直处于这种情况.
快速浏览工作现场确实表明HFT申请人需要C++知识,看看Wilmott论坛会显示所有从业者都在谈论C++.
这种情况有什么特别的原因吗?我原以为现代金融业务有点复杂,首选具有类型安全性,托管内存和丰富库的VM语言.这种生产力更高.此外,JIT编译器越来越好.他们可以在程序运行时进行优化,因此您认为他们使用该运行时信息来击败非托管程序的性能.
也许这些人正在用C++编写关键位并从托管环境(P/Invoke等)调用它们?那可能吗?
最后,有没有人有这方面的核心问题的经验,这就是为什么在这个领域,非托管代码毫无疑问优先于托管?
据我所知,HFT人员需要尽快对传入的市场数据作出反应,但这不一定是硬实时要求.如果你的速度慢,你的情况会更糟,这是肯定的,但是你不需要保证每次响应都有一定的速度,你只需要一个快速的平均值.
编辑
是的,到目前为止有几个很好的答案,但相当普遍(很好的基础).让我指出一下HFT人会运行什么样的程序.
主要标准是反应能力.当订单进入市场时,您希望成为第一个能够对其做出反应的订单.如果你迟到了,其他人可能会在你之前接受它,但是每个公司的策略都略有不同,所以如果一次迭代有点慢,你可能会好.
该程序全天运行,几乎没有用户干预.无论处理每个新的市场数据的功能是每秒运行几十(甚至几百)次.
这些公司通常对硬件的价格没有限制.
pga*_*ast 36
首先,1毫秒是HFT的永恒.如果您认为不是,那么更多地阅读有关域名的信息会更好.(这就像距离交易所100英里.)吞吐量和延迟是深深交织在一起的,因为任何基本排队理论教科书中的公式都会告诉你.相同的公式将显示抖动值(如果网络结构正确且您没有配置足够的内核,则通常由CPU队列延迟的标准偏差控制).
HFT套利的一个问题是,一旦你决定捕获差价,就有两条腿(或更多)来实现利润.如果你没有击中所有的腿,你可能会留下你真正不想要的位置(以及随后的损失) - 毕竟你是在进行套利而不是投资.
除非你的策略预测(非常近期!!!)未来(不管你信不信,这是非常成功的),你不希望持仓.如果距离交易所1毫秒,那么您订单的一小部分将不会被执行,您想要的将被取消.最有可能执行一条腿的人最终将失败者或至少没有盈利.
无论你的策略是出于什么样的论点,我们都说它最终会有55%/ 45%的赢/输比率.即使是赢/输比率的微小变化,盈利能力也会发生重大变化.
re:"运行数十个(甚至数百个)"似乎已经达到了数量级.即使每秒看20000个刻度也很低,尽管这可能是他正在观察的仪器组整天的平均值.
在任何给定的秒内,所见率都很高.我举个例子.在我的一些测试中,我会在当天中间查看7个场外交易股票(CSCO,GOOG,MSFT,EBAY,AAPL,INTC,DELL),此流的每秒费率可以从0 mps(非常非常罕见)到几乎近2000个报价和每秒峰值交易.(看看为什么我认为上面的20000很低.)
我为这个领域构建基础设施和测量软件,我们谈论的数字是100000和每秒数百万.我有C++生产者/消费者基础设施库,可以在生产者和消费者之间(32位,2.4 GHz核心)推送近5000000(500万)条消息/秒.这些是带有new,construct,enqueue,synchronize的 64字节消息,在生产者端同步,出列,触发每个字节,运行虚拟析构函数,免费在消费者方面.现在可以肯定的是,这是一个简单的基准测试,没有Socket IO(并且套接字IO可能很难看),就像在端点管道阶段的端点一样.它是所有自定义同步类,仅在空,自定义分配器,自定义锁定空闲队列和列表,偶尔STL(使用自定义分配器)时进行同步,但更常见的是自定义入侵集合(其中我有一个重要的库).我不止一次给这个领域的供应商提供了四倍(甚至更多)的吞吐量,而没有增加套接字端点的批处理.
我有OrderBook和OrderBook :: Universe类,当平均超过22000个仪器时,新的,插入,查找,部分填充,查找,第二次填充,擦除,删除序列少于2us.基准测试在插入第一次填充和最后一次填充之间连续迭代所有22000个仪器,因此不涉及廉价的缓存技巧.通过访问22000本不同的书籍来分离对同一本书的操作.这些不是真实数据的缓存特性.真实数据在时间上更加本地化,连续交易经常出现在同一本书中.
所有这些工作都需要仔细考虑所用集合的任何算法成本中的常量和缓存特性.(有时似乎K O(n)K O(n*log n)等等中的K被解雇有点过于明显)
我在Marketdata基础设施方面工作.即使考虑使用java或托管环境来完成这项工作也是不可思议的.当你可以通过C++获得这种性能时,我认为在托管环境下获得百万+/mps的表现是相当困难的)我无法想象任何重要的投资银行或对冲基金(对他们来说是25万美元的薪水)一流的C++程序员没有任何东西)没有使用C++.
有人在托管环境中真正获得2000000 +/mps的性能吗?我认识这个舞台上的一些人,没有人向我吹嘘.我认为在托管环境中2mm会有一些吹牛的权利.
我知道一个主要玩家的FIX命令解码器执行12000000场解码/秒.(3Ghz CPU)它是C++而且编写它的人几乎挑战任何人在托管环境中提出一些甚至是速度的一半的东西.
从技术上讲,这是一个有趣的领域,有很多有趣的性能挑战.在基础证券发生变化时考虑期权市场 - 可能会有6个未决价格点,有3个或4个不同的到期日.现在每笔交易大概有10-20个报价.这些报价可以触发期权中的价格变化.因此,对于每笔交易,期权报价可能会有100或200个变化.这只是一大堆数据 - 不是大型强子碰撞器碰撞检测器般的数据量,但仍然是一个挑战.它与处理键击有点不同.
甚至关于FPGA的争论还在继续.许多人认为在3GHZ商品HW上运行的编码良好的解析器可以胜过500MHz的FPGA.但即使稍微慢一点(不是说它们),基于FPGA的系统也可能倾向于具有更严格的延迟分布.(阅读"tend" - 这不是一个简单的陈述)当然,如果你有一个很棒的C++解析器,你可以通过Cfront推送,然后将其推送到FPGA图像生成器......但是另一个争论......
Jer*_*fin 27
其中很大一部分归结为事实与理论之间的简单差异.人们有先进的理论来解释为什么Java应该(或者至少可能)比C++更快.大多数参数与Java或C++ 本身几乎没有关系,而是与动态与静态编译有关,Java和C++实际上只是两者的例子(当然,可以静态编译Java,或者C++)动态).这些人中的大多数都有基准来"证明"他们的主张.当对这些基准进行详细检查时,很快就会发现,在很多情况下,他们采取了相当极端的措施来获得他们想要的结果(例如,在编译Java时,相当多的数据能够实现优化,但具体而言编译C++时禁用优化).
将其与计算机语言基准游戏进行比较,几乎任何人都可以提交条目,因此所有代码都倾向于在合理的程度上进行优化(在少数情况下甚至是不合理的程度).很明显,相当多的人认为这基本上是一种竞争,每种语言的拥护者都尽力"证明"他们的首选语言是最好的.由于任何人都可以提交任何问题的实施,特别糟糕的提交对整体结果影响不大.在这种情况下,C和C++成为明确的领导者.
更糟糕的是,如果有任何结果可能表明Java 比完全准确的更好.特别是,使用C或C++并且真正关心性能的人可以(并且经常会)使用英特尔的编译器而不是g ++.与g ++相比,这通常会使速度提高至少20%.
编辑(回应jalf提出的几点,但实际上太长,无法在评论中合理地拟合):
指针是优化者作家的噩梦.这真的夸大了事情(相当).指针导致混叠的可能性,这在某些情况下会阻止某些优化.也就是说,内联可以在很多时候防止不良影响(即,编译器可以检测是否存在别名而不是总是在假设可能存在的情况下生成代码).即使当代码不必须假设混叠,缓存最小化这样做击性能(即,在L1高速缓存的数据是只有微小比数据慢在寄存器).防止别名会有助于提高C++的性能,但不会像你想象的那么多.
垃圾收集器的分配速度要快得多.毫无疑问,许多C++实现中的默认分配器比大多数(当前)垃圾收集分配器提供的速度慢.这是平衡的(至少在一定程度上),因为C++中的分配往往在堆栈上,这也很快,而在GC语言中,几乎所有的分配通常都在堆上.更糟糕的是,在托管语言中,您通常会为每个对象单独分配空间,而在C++中,您通常会为范围内的所有对象分配空间.
同样,C++直接支持在全局和逐类的基础上替换分配器,所以当/如果分配速度确实是一个问题,它通常很容易修复.
最终,jalf是对的:这两点无疑都支持"托管"实施.这种改进的程度应该保持透视:它们不足以让动态编译的实现在很多代码上运行得更快 - 甚至不是从一开始就设计的基准测试尽可能地支持它们.
编辑2:我看到Jon Harrop试图插入他的两个(十亿分之一)的价值.对于那些谁不认识他,乔恩已经有臭名昭著的 巨魔 和 垃圾邮件发送者 的 年,并且似乎在寻找新的地面成播种杂草.我会尝试详细回复他的评论,但(对他来说是典型的)它只包含不合格的,不受支持的概括,其中包含的实际内容很少,无法进行有意义的回复.关于所有可以做的事情就是给旁观者公平的警告,他因为不诚实,自私自利,最好被忽视而闻名.
jal*_*alf 14
从理论上讲,JIT编译器可以执行很多优化,是的,但是你愿意等多久?一个C++应用程序可能需要数小时才能编译,因为它发生在离线状态,并且用户不会坐在那里轻拍他的手指并等待.
JIT编译器必须在几毫秒内完成.那么您认为哪些可以通过最复杂的优化来逃脱?
垃圾收集器也是一个因素.不是因为它本身比手动内存管理慢(我相信它的摊销成本非常好,绝对可以与手动内存处理相媲美),但它的可预测性较低.它几乎可以在任何一点引入停顿,这在需要极其响应的系统中可能是不可接受的.
当然,语言适合不同的优化.C++允许您编写非常严格的代码,几乎没有内存开销,并且许多高级操作基本上是免费的(比如类构造).
另一方面,在C#中,你浪费了大量的内存.简单地实例化一个类会带来很大的开销,因为Object必须初始化基类,即使你的实际类是空的.
C++允许编译器积极地剥离未使用的代码.在C#中,大部分必须在那里,因此可以通过反射找到它.
另一方面,C#没有指针,这是优化编译器的噩梦.托管语言中的内存分配比C++便宜得多.
无论哪种方式都有优势,因此期望您可以获得简单的"一个或另一个"答案是天真的.根据确切的源代码,编译器,操作系统,运行的硬件,一个或另一个可能更快.根据您的需求,原始性能可能不是第一目标.也许你对响应性更感兴趣,避免不可预测的失速.
通常,典型的C++代码的执行方式与等效的C#代码类似.有时更快,有时更慢,但两种方式可能都不是戏剧性的差异.
但同样,这取决于具体情况.这取决于您愿意花多少时间进行优化.如果你愿意花费尽可能多的时间,C++代码通常可以获得比C#更好的性能.这需要很多工作.
当然,另一个原因是大多数使用C++的公司已经拥有一个很大的C++代码库,他们并不特别想放弃它们.他们需要继续工作,即使他们逐渐将(部分)新组件迁移到托管语言.
这些公司通常对硬件的价格没有限制.
如果他们也不在乎软件的价格有多贵,那么我认为C++当然可以更快:例如,程序员可能会使用自定义分配或预先分配的内存; 和/或它们可以在内核中运行代码(避免环转换),或者在实时O/S上运行代码,和/或使其紧密耦合到网络协议栈.
| 归档时间: |
|
| 查看次数: |
4715 次 |
| 最近记录: |