将二进制数据和指令混合在一起是否存在缓存惩罚?

时间:2009-09-14 19:38:46

标签: c++ memory caching x86

我正在程序上生成128字节的块,其中一些设置的n字节头保留用于机器语言函数,我只是通过内联汇编调用。它们不是在任何地方定义的,而是在运行时生成分配到内存中的页面,并具有执行权限。但是,我想保留这些块的末尾(128-n)字节,用于存储在这些函数中使用的数据,因为它能够将内存偏移调用缩小到8位而不是32位,并且(可能?)帮助缓存。但是,缓存是我所担心的。

假设我的处理器同时具有数据缓存和指令缓存,那么这种典型处理器处理这种格式的效果如何呢?它是否会尝试将我的指令后的数据作为指令加载到指令缓存中?这可能会导致显着的性能损失,因为处理器试图找出如何处理这些垃圾和可能无效的“指令”,因为它们会在几乎每次调用时都在附近浮动?一旦我在数据段的头部首次访问它,它是否会将这些数据加载到正常的L1 / L2缓存中,或者此时它是否会被混淆?

编辑:我想我应该补充一点,吞吐量的优化显然是非常重要的。在这种情况下,优化的混乱或困难无关紧要,只需最小化代码的执行时间。

3 个答案:

答案 0 :(得分:2)

在现今的处理器上,L2和更高版本的缓存应该没问题,因为它们无论如何都是混合的。 L1缓存(有时是密切相关的结构,如跟踪缓存,微操作缓存等)可能会受到这种欺骗的影响。从一个微体系结构到另一个体系结构的影响可能也会有所不同。我希望任何跟踪/微操作缓存都不会因无法解码的数据而受到惩罚,但我不会指望它。您必须尝试并根据与您的应用程序相关的微体系结构进行基准测试。

编辑:您是否采用这种方式来最小化生成的代码的大小,或者在您获得指令或其他原因时保证将数据保存在缓存中?这可能比您真正需要的更复杂。同样,基准和分析是你的朋友。

答案 1 :(得分:1)

由于块将被加载到L1指令和数据缓存中,因此会有一些惩罚,这将浪费空间。浪费的空间量取决于高速缓存块的大小,但它可能不会被减少的指令大小的节省所抵消。 L2缓存及以下通常在指令和数据之间共享,不会受到影响。

CPU可能不会尝试解码块中的数据,因为您可能有一个返回或无条件分支作为最后一条指令。任何理智的CPU都不会在此之后获取或解码指令。

答案 2 :(得分:1)

正如其他答案所指出的,您可能遇到的唯一性能损失是在代码L1和数据L1中具有相同的缓存行,这将浪费一些空间(甚至这不会是一个真正的问题,因为根据他们的需要填充缓存。据我所知,对两个缓存中都存在缓存行没有任何限制。)

另一个答案忽略了一点。如果您计划修改接近代码的数据,则很可能会触发自我修改代码方案,这会导致非常严重的惩罚。

自修改代码(SMC)将刷新整个流水线,直到存储指令,假设由于修改而推测性地执行的任何指令可能不正确。大多数现代x86处理器的深层管道意味着每个这样的刷新都会导致许多周期的惩罚,而没有指令完成。

如果您确保您的代码段附近没有商店,那么您应该没问题。