首页 文章

在Intel CPU上缓存对齐的内存分配

提问于
浏览
2

最近我遇到了英特尔TBB可扩展分配器的问题 . 基本使用模式如下,

  • 分配了一些大小为 N * sizeof(double) 的向量

  • 生成一个随机整数 M ,使 M >= N / 2 && M <= N .

  • 访问每个向量的第一个 M 元素 .

  • 重复步骤2. 1000次 .

我将 M 设置为随机,因为我不想基于固定长度的基准性能 . 相反,我希望在一系列矢量长度上获得平均性能 .

对于 N 的不同值,程序性能差别很大 . 这并不罕见,因为我正在测试的功能旨在优先考虑大型 N 的性能 . 然而,当我试图对性能与 N 之间的关系进行基准测试时,我发现在某一点上,当 N1016 增加到 1017 时,存在两倍的差异 .

我的第一直觉是 N = 1016 的性能退化与较小的矢量大小无关,而是有一些事情要做缓存 . 最有可能是虚假分享 . 品尝下的功能使用SIMD指令,但没有堆栈内存 . 它从第一个向量中读取一个32字节的元素,并在计算之后将32个字节写入第二个(和第三个)向量 . 如果发生错误共享,可能会丢失几十个周期,这正是我观察到的性能损失 . 一些分析证实了这一点 .

最初我将每个向量与32字节边界对齐,用于AVX指令 . 为了解决这个问题,我将向量与64字节边界对齐 . 但是,我仍然观察到相同的性能损失 . 对齐128字节解决问题 .

我做了一些挖掘 . 英特尔TBB有 cache_aligned_allocator . 在其源中,内存也以128个字节对齐 .

这就是我没有't understand. If I am not mistaken, modern x86 CPU'的缓存行为64字节 . CPUID 证实了这一点 . 以下是正在使用的CPU的基本缓存信息,从我使用CPUID编写的小程序中提取来检查功能,

Vendor    GenuineIntel
Brand     Intel(R) Core(TM) i7-4960HQ CPU @ 2.60GHz

====================================================================================================
Deterministic Cache Parameters (EAX = 0x04, ECX = 0x00)
----------------------------------------------------------------------------------------------------
Cache level                             1           1           2           3           4           
Cache type                              Data        Instruction Unified     Unified     Unified     
Cache size (byte)                       32K         32K         256K        6M          128M        
Maximum Proc sharing                    2           2           2           16          16          
Maximum Proc physical                   8           8           8           8           8           
Coherency line size (byte)              64          64          64          64          64          
Physical line partitions                1           1           1           1           16          
Ways of associative                     8           8           8           12          16          
Number of sets                          64          64          512         8192        8192        
Self initializing                       Yes         Yes         Yes         Yes         Yes         
Fully associative                       No          No          No          No          No          
Write-back invalidate                   No          No          No          No          No          
Cache inclusiveness                     No          No          No          Yes         No          
Complex cache indexing                  No          No          No          Yes         Yes         
----------------------------------------------------------------------------------------------------

此外,在英特尔TBB的源代码中,128字节对齐的标记是注释,这是为了向后兼容 .

那么为什么我的情况下64字节对齐不够呢?

1 回答

  • 2

    你被conflict misses击中 . 从1016到1017时发生的原因是您开始使用关联列表中的最后一个缓存行 .

    你的缓存是32K 8路,所以每套都是4K . 您的64字节缓存行可以容纳8个双精度数 . 但你的1017-1024矢量使用8K而不是4K ??? 1024 * sizeof(双),你使用N / 2-> N,所以你使用(除了恰好N / 2)一些相同的低地址位组合每个矢量两次 .

    在您使用了所有L1缓存之前,您不会遇到冲突命中问题,而您现在已经接近了 . 使用1个向量进行读取,使用2个向量进行写入,所有8K长,因此使用24K,如果在计算过程中使用8K额外数据,则会增加驱逐所选数据的机会 .

    请注意,您只使用向量的第一部分,但它们之间的冲突从未如此 .

    当你从1016跳到1017时,你将能够观察到L1缓存未命中的增加 . 当你超过1024倍时,性能损失会在短时间内消失,直到你达到L1缓存容量未命中 .

    <在此处对图形进行成像,显示当使用所有8组时的尖峰>

    来自Ulrich Drepper的精彩文章:“Memory part 5: What programmers can do
    enter image description here

相关问题