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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/symfony/6.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++ 原子操作比锁定时间长(无争用)_C++_Multithreading_Locking_Atomic_Compiler Optimization - Fatal编程技术网

C++ 原子操作比锁定时间长(无争用)

C++ 原子操作比锁定时间长(无争用),c++,multithreading,locking,atomic,compiler-optimization,C++,Multithreading,Locking,Atomic,Compiler Optimization,我试图在没有争用的情况下测量各种同步选项的开销。我使用以下程序: #include <atomic> #include <chrono> #include <iostream> #include <mutex> void function() { static volatile uint64_t counter = 0; counter++; } void function2() { std::atomic<uin

我试图在没有争用的情况下测量各种同步选项的开销。我使用以下程序:

#include <atomic>
#include <chrono>
#include <iostream>
#include <mutex>

void function() {
    static volatile uint64_t counter = 0;
    counter++;
}

void function2() {
    std::atomic<uint64_t> counter2 = 0;
    counter2++;
}

int main() {
    // warm up the cache
    std::mutex lock;
    for( int i=0; i<1'000'000; ++i ) {
        std::lock_guard<std::mutex> locker(lock);
        function();
        function2();
    }

    std::cout<<"Starting test\n";
    auto start = std::chrono::high_resolution_clock::now();
    for( int i=0; i<1'000'000; ++i ) {
        std::lock_guard<std::mutex> locker(lock);
        function();
    }
    auto end = std::chrono::high_resolution_clock::now();
    std::cout<<"  With lock took "<<std::chrono::ceil<std::chrono::nanoseconds>(end-start).count()<<"ns\n";

    start = std::chrono::high_resolution_clock::now();
    for( int i=0; i<1'000'000; ++i ) {
        function();
    }
    end = std::chrono::high_resolution_clock::now();
    std::cout<<"    No lock took "<<std::chrono::ceil<std::chrono::nanoseconds>(end-start).count()<<"ns\n";

    start = std::chrono::high_resolution_clock::now();
    for( int i=0; i<1'000'000; ++i ) {
        function2();
    }
    end = std::chrono::high_resolution_clock::now();
    std::cout<<"Atomic lock took "<<std::chrono::ceil<std::chrono::nanoseconds>(end-start).count()<<"ns\n";
}
因此,无论是否锁定,结果都相当相似(通常不锁定的速度稍快),但使用原子操作,我得到了x6性能的提升

逻辑上说,如果没有争用,相关变量都将是运行中的CPU缓存的本地变量,并且所有同步选项或多或少都会导致相同的性能


我遗漏了什么?

问题在于基准测试程序

第一个是未声明
std::atomic
,导致在每次迭代中使用一个新的。第二个问题是程序没有使用
-pthread
编译,导致锁定代码成为no-op(这解释了为什么带锁定的代码与不带锁定的代码运行速度相同)

解决这两个问题会产生:

Starting test
  With lock took 21013047ns
    No lock took 2125868ns
Atomic lock took 6744567ns

因此,原子方法大约比不锁定慢3倍,而实际锁定大约慢10倍。

我想知道。。。
std::atomic::isu lock\u free
是否返回true?我在编译该测试时遇到了非常奇怪的问题。我确实检查过装配。它使用了
lock add
,因此无论
是无锁的
返回什么,实际上它都是无锁的。我会尝试使用多个线程运行测试:)@MFnx您可以,但这里的重点是测量无争用的性能。您的函数可以做非常不同的事情。一个重复增加相同的
uint64\u t
,而另一个在每次迭代中创建一个新的
std::atomic
。将其改为比较,原子操作胜出了很多。我认为原子操作在单线程情况下没有得到优化,因为您仍然可以在信号处理程序中使用它们。如果有非信号处理程序选项,则可以对其进行优化。无论如何,像原子对象一样的本地“寄存器”可以被优化掉!
Starting test
  With lock took 21013047ns
    No lock took 2125868ns
Atomic lock took 6744567ns