Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 锁定空闲队列,加载与未加载CPU_C++_Multithreading_Performance_X86_Lock Free - Fatal编程技术网

C++ 锁定空闲队列,加载与未加载CPU

C++ 锁定空闲队列,加载与未加载CPU,c++,multithreading,performance,x86,lock-free,C++,Multithreading,Performance,X86,Lock Free,我的CPU是Corei7(4个物理核/8个逻辑核)。我正在测试自由锁定队列的实现。测试是什么?我只是创建了很多线程(“pusher”和“popper”),它们推/弹出元素。我注意到当。。。CPU已加载。因此,当CPU没有相对负载时,它工作得比较慢(相对较多)。而且,当它被加载时,它工作得更快 如何理解它?我认为这是因为“popper”和“pusher”必须竞争“head/”tail”。(我的意思是由于内存管理而增加节点)。如果popper/pusher更少,那么计数器就更低。但是,请注意,它实际

我的CPU是Corei7(4个物理核/8个逻辑核)。我正在测试自由锁定队列的实现。测试是什么?我只是创建了很多线程(“pusher”和“popper”),它们推/弹出元素。我注意到当。。。CPU已加载。因此,当CPU没有相对负载时,它工作得比较慢(相对较多)。而且,当它被加载时,它工作得更快

  • 如何理解它?我认为这是因为“popper”和“pusher”必须竞争“head/”tail”。(我的意思是由于内存管理而增加节点)。如果popper/pusher更少,那么计数器就更低。但是,请注意,它实际上可以自由锁定(我想是这样:))

  • 这是否意味着在某些情况下我应该让线程休眠2毫秒?可能是10毫秒(这对于CPU来说太长了)。我不确定


  • 在内核之间跳转缓存线成本很高。一个内核在试图修改同一内存时,推/弹出速度比相互竞争的4个内核快4倍以上,这听起来很合理

    因此,问题似乎在于确定所有线程的总挂钟时间或总CPU时间的变化告诉您代码是否正确


    换句话说:您正在测试最大争用情况,在这种情况下,您的线程将所有时间都用于推送和弹出,而不做任何其他工作。在使用此队列的实际代码中,线程所做的其他工作将限制对队列的访问速率,可能会限制很多,因此线程会经常互相踩脚ess。(争用可能会对cmpxchg循环造成严重的性能影响,因为每次只有一个CPU会成功,其余的CPU每次都会重试。)

    相关:在测试在高争用和低争用情况下使用锁的并行算法时,提出了相同的观点


    也许可以尝试使用一些线程进行只读访问的基准测试

    当很多访问都是读取时,无锁算法真的很有用。我猜队列通常会弹出,而不仅仅是读取,所以这对于实际使用来说可能没有意义。但我打赌,如果您的一些线程只是读取共享队列而不是更新它,您会看到不同的结果。(例如,将其作为链接列表从头到尾遍历)


    在编写代码时,另一个有趣的尝试是:在从基准测试中的某个共享内存加载之前添加
    pause
    指令(
    \u mm\u pause()
    ),以避免内存顺序错误推测。(即,在允许负载全局可见之前,CPU推测性地使用加载的值,然后在负载被假定为全局可见时,当该值被另一个内核更改时,CPU必须回滚).请记住,
    pause
    在Haswell上休眠约5个周期,但在Skylake上休眠约100个周期,因此,即使您在Haswell上的非合成基准测试中看到它的加速,将其保留下来供将来的CPU实际使用可能是个坏主意

    请注意,
    pause
    lock
    ed read-modify-write指令之前是没有用的;它们已经在等待来自其他内核的写入


    通常情况下,你先轻松加载一个cmpxchg,然后再加载一个cmpxchg,所以我建议在加载之前暂停一下。

    在内核之间跳转缓存线是很昂贵的。一个内核在尝试修改同一内存时,推/弹出的速度比相互竞争的4个内核快4倍以上,这听起来很合理

    因此,问题似乎在于确定所有线程的总挂钟时间或总CPU时间的变化告诉您代码是否正确


    换句话说:您正在测试最大争用情况,在这种情况下,您的线程将所有时间都用于推送和弹出,而不做任何其他工作。在使用此队列的实际代码中,线程所做的其他工作将限制对队列的访问速率,可能会限制很多,因此线程会经常互相踩脚ess。(争用可能会对cmpxchg循环造成严重的性能影响,因为每次只有一个CPU会成功,其余的CPU每次都会重试。)

    相关:在测试在高争用和低争用情况下使用锁的并行算法时,提出了相同的观点


    也许可以尝试使用一些线程进行只读访问的基准测试

    当很多访问都是读取时,无锁算法真的很有用。我猜队列通常会弹出,而不仅仅是读取,所以这对于实际使用来说可能没有意义。但我打赌,如果您的一些线程只是读取共享队列而不是更新它,您会看到不同的结果。(例如,将其作为链接列表从头到尾遍历)


    在编写代码时,另一个有趣的尝试是:在从基准测试中的某个共享内存加载之前添加
    pause
    指令(
    \u mm\u pause()
    ),以避免内存顺序错误推测。(即,在允许负载全局可见之前,CPU推测性地使用加载的值,然后在负载被假定为全局可见时,当该值被另一个内核更改时,CPU必须回滚).请记住,
    pause
    在Haswell上休眠约5个周期,但在Skylake上休眠约100个周期,因此,即使您在Haswell上的非合成基准测试中看到它的加速,将其保留下来供将来的CPU实际使用可能是个坏主意

    请注意,
    pause
    lock
    ed read-modify-write指令之前是没有用的;它们已经在等待来自其他内核的写入


    通常情况下,你会先进行一个宽松的加载,然后是一个cmpxchg,所以我建议在加载之前暂停一下。

    你是说如果你在一个空的CPU上运行测试,它会比你运行ex时运行得慢吗