C ++独立数据的多线程性能

时间:2015-11-16 10:52:51

标签: c++ multithreading performance

让我们有一个非常简单的C ++类,只有一个数据成员:

class Container {
public:
    std::vector<Element> elements;
    Container(int elemCount);
};

现在创建N个线程,执行一项非常简单的任务:

  1. 创建具有特定矢量大小的本地Container
  2. 遍历向量并简单地递增每个元素的val
  3. 重复步骤2 10.000次(以秒为单位,而不是ms)
  4. 完整的代码清单可在Pastebin

    上找到

    根据CoreInfo我的CPU(Intel Core i5 2400)有4个内核,每个内核都有自己的L1 / L2缓存:

    Logical to Physical Processor Map:
    *---  Physical Processor 0
    -*--  Physical Processor 1
    --*-  Physical Processor 2
    
    Logical Processor to Cache Map:
    *---  Data Cache          0, Level 1,   32 KB, Assoc   8, LineSize  64
    *---  Instruction Cache   0, Level 1,   32 KB, Assoc   8, LineSize  64
    *---  Unified Cache       0, Level 2,  256 KB, Assoc   8, LineSize  64
    -*--  Data Cache          1, Level 1,   32 KB, Assoc   8, LineSize  64
    -*--  Instruction Cache   1, Level 1,   32 KB, Assoc   8, LineSize  64
    -*--  Unified Cache       1, Level 2,  256 KB, Assoc   8, LineSize  64
    --*-  Data Cache          2, Level 1,   32 KB, Assoc   8, LineSize  64
    --*-  Instruction Cache   2, Level 1,   32 KB, Assoc   8, LineSize  64
    --*-  Unified Cache       2, Level 2,  256 KB, Assoc   8, LineSize  64
    ---*  Data Cache          3, Level 1,   32 KB, Assoc   8, LineSize  64
    ---*  Instruction Cache   3, Level 1,   32 KB, Assoc   8, LineSize  64
    ---*  Unified Cache       3, Level 2,  256 KB, Assoc   8, LineSize  64
    ****  Unified Cache       4, Level 3,    6 MB, Assoc  12, LineSize  64
    ---*  Physical Processor 3
    

    对于最多100,000个元素的矢量大小,时间与预期完全相同:

    Elements count: 100.000
    
    Threads: 1
    loops: 10000 ms: 650
    
    Threads: 4
    loops: 2500 ms: 168
    loops: 2500 ms: 169
    loops: 2500 ms: 169
    loops: 2500 ms: 171
    

    但是,对于更大的矢量大小,多核的性能是:

    Elements count: 300.000
    
    Threads: 1
    loops: 10000 ms: 1968
    
    Threads: 4
    loops: 2500 ms: 3817
    loops: 2500 ms: 3864
    loops: 2500 ms: 3927
    loops: 2500 ms: 4008
    

    我的问题:

    1. 有人可以向我解释一下这个原因吗?这是假共享吗?如果是这样,如果线程 NOT 共享任何数据并且所有内核都有自己的L1 / L2缓存和缓存行,那么这怎么可能呢?
    2. 在多个线程中处理独立数据时,是否有可能达到(或接近)线性加速效率?
    3. 编辑:感谢所有答案,到目前为止。关于你的问题:

      @ user2079303:元素只包含一个双数据记录器。的sizeof(元件)= 8。有关完整的源代码,请参阅Pastebin

      @bku_drytt:resize()是正确的。我的目的是在每个线程中创建一个包含elemCount元素的向量(无论它们的初始值如何)。

      @JorgeGonzálezLorenzo:你对共享L3缓存完全正确。我执行了另一组测试,仅限单线程:

      Elements count: 50.000
      Threads: 1
      loops: 50000 ms: 1615
      
      Elements count: 200.000 (4 times bigger)
      Threads: 1
      loops: 50000 ms: 1615 (slightly more than 4 time bigger)
      
      Elements count: 800.000 (even 4 times bigger)
      Threads: 1
      loops: 50000 ms: 42181 (MUCH more than 4 time bigger)
      

1 个答案:

答案 0 :(得分:0)

您正在使用4个线程填充L3共享缓存(因为每个线程有一个向量需要x4存储),因此导致许多缓存未命中,而在单线程执行中,向量适合它。 L1和L2是每个核心,但L3不是。公平的比较是使用x4更大的向量与4个线程执行相比运行单线程执行。