sprintf vs strcpy - 使用更多内存和快速复制或几乎没有内存和慢速复制?

时间:2015-02-22 21:46:57

标签: c performance caching

我正在编写延迟关键应用程序(自制HFT交易系统)。我有这样的代码,只是将uint64转换为string:

    // TODO: cache sprintf, use strcpy? measure?
    sprintf(dest, "%" PRIu64, divRes.quot);

这里divRes.quot是整数,保证在1到1 000 000之间。所以我可以预先分配(相当大)数组和"缓存"每一个价值。然后我可以执行strcpy(dest, cache[divRes.quot]).

乍一看它必须明显加快,因为strcpy必须明显快于sprintf。但请注意,我使用的是巨大的数组,几乎肯定无法完全加载到CPU缓存中。所以第二种方法几乎肯定会进入主存。虽然在第一种方法中,我很可能会留在CPU缓存中(甚至可能在最快的L1缓存中?!)

所以平均来说会更快:

  • CPU缓存中的慢功能
  • 可以访问主内存的快速功能吗?

我认为这取决于一个函数比另一个函数快多少以及CPU缓存访问速度比主内存访问速度快多少。

我认为写一个真正的测试非常困难。因为在实际应用中,整体系统负载会有所不同,因此缓存/内存使用会有所不同,这可能会大大改变。

请注意我不关心可读性,维护等,我只需要速度。

1 个答案:

答案 0 :(得分:1)

为了使表查找运行良好,您必须经常这样做(在具有大缓存的CPU上),因为大多数情况下表的大部分时间都在缓存中#39这样做。该表占用大约7兆字节的内存,因此除非缓存相当大,并且您一次转换数百万个数字,因此大多数访问都是缓存,它几乎肯定是一个网络失利。

通过我的计算,它可能需要大约100个时钟才能使用正常除法(~5格+6加法)转换单个数字。从主存储器读取通常需要200个处理器时钟,因此您需要大约50%的缓存命中率才能实现收支平衡。

就个人而言,我怀疑我是否使用这些方法中的任何一种。相反,我可能会做混合动力。我将数字除以1000,然后进行两次表格查找(一次是红利,另一次是余下)。

优点是这会将表大小减少到大约4千字节,并且每个表条目的使用量增加大约1000倍。假设您要转换至少几百个(左右)随机分布在一次数字,你可以指望几乎100%的缓存命中率。凭借较高的缓存命中率,我们可以计划一个分区加上两个来自缓存的负载,总共大约25个时钟,或者大约是我们对天真转换的预期速度的4倍。