std :: lock_guardをstd :: mutex :: lock()よりも高速にするにはどうすればよいですか?


9

私は同僚とlock_guardについて議論しており、彼は、lock_guardクラスのインスタンス化とインスタンス化のコストのために、lock_guardはmutex :: lock()/ mutex :: unlock()よりもおそらく遅いと提案しました。

次に、この簡単なテストを作成しました。驚いたことに、lock_guardを使用したバージョンは、mutex :: lock()/ mutex :: unlock()を使用したバージョンよりもほぼ2倍高速です。

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

std::mutex m;
int g = 0;

void func1()
{
    m.lock();
    g++;
    m.unlock();
}

void func2()
{
    std::lock_guard<std::mutex> lock(m);
    g++;
}

int main()
{
    auto t = std::chrono::system_clock::now();
    for (int i = 0; i < 1000000; i++)
    {
        func1();
    }

    std::cout << "Take: " << std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now() - t).count() << " ms" << std::endl;

    t = std::chrono::system_clock::now();
    for (int i = 0; i < 1000000; i++)
    {
        func2();
    }

    std::cout << "Take: " << std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now() - t).count() << " ms" << std::endl;

    return 0;
}

私のマシンでの結果:

Take: 41 ms
Take: 22 ms

誰かがこれを理由と方法を明確にできますか?


2
何回測定しましたか?
artm

7
コンパイラフラグを投稿してください...ベンチマークは最適化レベルによって異なります...
Macmade

10
プロヒント:このような測定を行って、必ずそれだけで問題を引き起こして風邪データ/命令をでないようにするためのスワップ:coliru.stacked-crooked.com/a/81f75a1ab52cb1cc
NathanOliver

2
このような測定を行う際に役立つもう1つのことは、全体をより大きなループに入れて、測定セット全体を実行する(たとえば、各実行を20回)ようにすることです。通常、後の測定値は実際に意味のあるものになります。それまでに、キャッシュは長期的に見られる可能性のある動作に落ち着いているからです。
Mark Phaedrus

2
場合でも、std::lock_guardあなたは速度ゲインを使用しての他の利点無効にしないこと、それはパフォーマンスの面で重要なことを証明できない限り少し遅く、だったstd::lock_guard(主にRAIIを)。g++投げることができるもの、または将来さらに複雑になる可能性のあるものに変更される可能性があるものがある場合は、ロックを所有するために何らかのオブジェクトを使用する必要があります。
フランソワアンドリュー

回答:


6

リリースビルドは、両方のバージョンで同じ結果を生成します。

DEBUGビルドショー〜33%長い時間がfunc2。をfunc2使用__security_cookieして呼び出す逆アセンブリで私が見る違い@_RTC_CheckStackVars@8

デバッグのタイミングをとっていますか?

編集:さらに、RELEASE逆アセンブリを調べていると、mutexメソッドが2つのレジストリに保存されていることがわかりました。

010F104E  mov         edi,dword ptr [__imp___Mtx_lock (010F3060h)]  
010F1054  xor         esi,esi  
010F1056  mov         ebx,dword ptr [__imp___Mtx_unlock (010F3054h)]  

そして、の両方から同じように呼ばれるfunc1func2

010F1067  call        edi  
....
010F107F  call        ebx  
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.