我正在编写延迟关键型应用程序(自制的HFT交易系统)。我有这样的代码,只是将uint64转换为字符串:
// TODO: cache sprintf, use strcpy? measure?
sprintf(dest, "%" PRIu64, divRes.quot);
这里的
divRes.quot
是整数,保证在1到1000000之间。因此,我可以预分配(相当大的)数组并“缓存”每个单个值。然后我可以执行strcpy(dest, cache[divRes.quot]).
乍一看,它必须快得多,因为
strcpy
必须比sprintf
快得多。但是请注意,我使用的大型数组几乎肯定不能完全加载到CPU缓存中。因此,第二种方法几乎肯定会进入主存储器。在第一种方法中,我很可能会保留在CPU缓存中(甚至可能是最快的L1缓存?!)因此,平均而言,速度会更快:
CPU缓存中的慢速功能
具有访问主存储器的快速功能?
我认为这取决于一个功能比另一个功能快多少,以及CPU缓存访问比主内存访问快多少。
我想写一个真正的测试非常困难。因为在实际的应用程序中,整个系统的负载将有所不同,因此缓存/内存的使用将有所不同,因此可能会发生很大的变化。
请注意,我不在乎可读性,维护性等,我只需要速度。
最佳答案
为了使表查找正常进行,您必须经常执行此操作(在具有高速缓存的CPU上),以使大部分表在大多数情况下都处于高速缓存中。该表占用大约7兆字节的内存,因此,除非缓存非常大,并且一次要转换数百万个数字,因此大多数访问都要缓存,所以几乎肯定会造成净损失。
根据我的判断,使用正常的除法(〜5除法+ 6加法)转换单个数字可能需要大约100个时钟。从主内存读取数据通常需要200个处理器时钟左右,因此您需要大约50%的高速缓存命中率才能达到收支平衡。
就我个人而言,我怀疑我会使用其中一种方法。相反,我可能会做一个混合动力车。我将数字除以1000,然后进行两次表查找(一个与除数,另一个与余数)。
好处是,这会将表的大小减小到大约4 KB,并使每个表条目的使用增加大约1000倍。假设您一次要转换至少几百个(或大约几百个)随机分布的数字,您可能可以依靠接近100%的缓存命中率。有了较高的高速缓存命中率,我们可以计划一个分区加上两个高速缓存加载,总共大约需要25个时钟,这大约是我们幼稚转换所期望的大约4倍的速度。
关于c - sprintf vs strcpy-使用更多的内存和快速复制还是几乎没有内存和慢速复制?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/28663679/