gpt4 book ai didi

c++ - 为什么在这种无竞争的情况下原子比锁慢得多?

转载 作者:搜寻专家 更新时间:2023-10-31 00:00:42 25 4
gpt4 key购买 nike

我使用原子而不是锁写了一些东西,并且对我的情况慢得多感到困惑,我写了以下迷你测试:

#include <pthread.h>
#include <vector>

struct test
{
test(size_t size) : index_(0), size_(size), vec2_(size)
{
vec_.reserve(size_);
pthread_mutexattr_init(&attrs_);
pthread_mutexattr_setpshared(&attrs_, PTHREAD_PROCESS_PRIVATE);
pthread_mutexattr_settype(&attrs_, PTHREAD_MUTEX_ADAPTIVE_NP);

pthread_mutex_init(&lock_, &attrs_);
}

void lockedPush(int i);
void atomicPush(int* i);

size_t index_;
size_t size_;
std::vector<int> vec_;
std::vector<int> vec2_;
pthread_mutexattr_t attrs_;
pthread_mutex_t lock_;
};

void test::lockedPush(int i)
{
pthread_mutex_lock(&lock_);
vec_.push_back(i);
pthread_mutex_unlock(&lock_);
}

void test::atomicPush(int* i)
{
int ii = (int) (i - &vec2_.front());
size_t index = __sync_fetch_and_add(&index_, 1);
vec2_[index & (size_ - 1)] = ii;
}

int main(int argc, char** argv)
{
const size_t N = 1048576;
test t(N);

// for (int i = 0; i < N; ++i)
// t.lockedPush(i);

for (int i = 0; i < N; ++i)
t.atomicPush(&i);
}

如果我取消注释 atomicPush 操作并使用 time(1) 运行测试,我会得到如下输出:

real    0m0.027s
user 0m0.022s
sys 0m0.005s

如果我运行调用原子事物的循环(看似不必要的操作就在那里,因为我希望我的函数看起来尽可能像我更大的代码所做的那样)我得到这样的输出:

real    0m0.046s
user 0m0.043s
sys 0m0.003s

我不确定为什么会发生这种情况,因为我预计在这种情况下原子会比锁更快......

当我使用 -O3 编译时,我看到锁和原子更新如下:

lock:
real 0m0.024s
user 0m0.022s
sys 0m0.001s

atomic:
real 0m0.013s
user 0m0.011s
sys 0m0.002s

尽管如此,在我较大的应用程序中,锁的性能(单线程测试)仍然做得更好..

最佳答案

无竞争的互斥量可以非常快速地锁定和解锁。对于原子变量,您总是付出一定的内存同步代价(特别是因为您甚至没有使用松散排序)。

您的测试用例太天真了,没有用处。您必须测试竞争激烈的数据访问场景。

一般来说,原子 很慢(它们阻碍了巧妙的内部重新排序、流水线和缓存),但它们允许无锁代码,确保整个程序可以使 一些进步。相比之下,如果您在持有锁时被换出,每个人都必须等待。

关于c++ - 为什么在这种无竞争的情况下原子比锁慢得多?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12498483/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com