ロックではなくアトミックを使用して何かを作成し、私の場合は非常に遅いことに当惑し、次のミニテストを作成しました。
#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
私のより大きなアプリでは、ロックのパフォーマンス(シングルスレッドテスト)は依然として改善されていますが..