当没有争用时,我试图度量各种同步选项的开销。我使用以下程序:
#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";
}用gcc或clang编写,我得到了类似的结果:
$ clang++-7 -g -O3 -std=c++2a locking.cpp -o locking && ./locking
Starting test
With lock took 2099204ns
No lock took 2126724ns
Atomic lock took 12922543ns因此,不管是否锁定,结果都是相似的(通常没有锁定会稍微快一些),但是对于原子操作,我的x6性能会受到影响。
逻辑上说,在没有争用的情况下,相关变量都是运行中的CPU缓存的本地变量,而所有同步选项都将产生或多或少的相同性能。
我遗漏了什么?
发布于 2019-06-12 06:40:52
问题在于基准测试程序。
第一种情况是,std::atomic没有被声明为static,导致在每次迭代时使用一个新的。第二个问题是程序不是用-pthread编译的,导致锁定代码变成无操作(这解释了为什么具有锁定的代码以与不带锁的代码相同的速度运行)。
解决这两个问题的结果是:
Starting test
With lock took 21013047ns
No lock took 2125868ns
Atomic lock took 6744567ns所以原子方法比没有锁定慢3倍,而实际锁定大约慢10倍。
https://stackoverflow.com/questions/56555372
复制相似问题