Pertanyaan Mengapa std :: atom jauh lebih lambat daripada bool yang mudah menguap?


Saya telah menggunakan bool volatil selama bertahun-tahun untuk kontrol eksekusi thread dan bekerja dengan baik

// in my class declaration
volatile bool stop_;

-----------------

// In the thread function
while (!stop_)
{
     do_things();
}

Sekarang, karena c ++ 11 menambahkan dukungan untuk operasi atom, saya memutuskan untuk mencobanya

// in my class declaration
std::atomic<bool> stop_;

-----------------

// In the thread function
while (!stop_)
{
     do_things();
}

Tapi itu beberapa kali lipat lebih lambat daripada volatile bool!

Kasus uji sederhana yang saya tulis membutuhkan waktu sekitar 1 detik untuk diselesaikan volatile bool pendekatan. Dengan std::atomic<bool> Namun saya sudah menunggu sekitar 10 menit dan menyerah!

Saya mencoba menggunakannya memory_order_relaxed bendera dengan load dan store untuk efek yang sama.

Platform saya: Windows 7 64 bit Gcc MinGW 4.6.x

Apa yang saya lakukan salah?

UPD

Ya, saya tahu bahwa volatile tidak membuat thread variabel aman. Pertanyaan saya bukan tentang volatil, ini tentang mengapa atom sangat lambat.

UPD2 @all, terima kasih atas komentar Anda - Saya akan mencoba semua saran ketika saya masuk ke mesin saya malam ini.


32
2017-10-30 09:15


asal


Jawaban:


Kode dari "Olaf Dietsche"

 USE ATOMIC
 real   0m1.958s
 user   0m1.957s
 sys    0m0.000s

 USE VOLATILE
 real   0m1.966s
 user   0m1.953s
 sys    0m0.010s

JIKA ANDA MENGGUNAKAN GCC SMALLER 4.7

http://gcc.gnu.org/gcc-4.7/changes.html

Dukungan untuk operasi atom yang menentukan model memori C ++ 11 / C11 telah ditambahkan. Rutinitas __atomic baru ini menggantikan rutin bawaan __sync yang ada.

Dukungan atom juga tersedia untuk blok memori. Instruksi bebas-lock akan digunakan jika blok memori memiliki ukuran dan pelurusan yang sama dengan tipe integer yang didukung. Operasi atom yang tidak memiliki dukungan bebas-lock dibiarkan sebagai fungsi panggilan. Satu set fungsi perpustakaan tersedia di wiki atom GCC di bagian "Perpustakaan Atom Eksternal".

Jadi ya .. hanya solusinya adalah upgrade ke GCC 4.7


30
2017-10-30 11:35



Karena saya penasaran dengan ini, saya menguji sendiri pada Ubuntu 12.04, AMD 2.3 GHz, gcc 4.6.3.

#if 1
#include <atomic>
std::atomic<bool> stop_(false);
#else
volatile bool stop_ = false;
#endif

int main(int argc, char **argv)
{
    long n = 1000000000;
    while (!stop_) {
        if (--n < 0)
            stop_ = true;
    }

    return 0;
}

Dikompilasi dengan g++ -g -std=c++0x -O3 a.cpp

Meskipun, kesimpulan yang sama dengan @aleguna:

  • hanya bool:

    0m0.004s nyata
      pengguna 0m0.000s
      sys 0m0.004s

  • volatile bool:

    $ waktu ./a.out
      0m1.413s nyata
      pengguna 0m1.368s
      sys 0m0.008s

  • std::atomic<bool>:

    $ waktu ./a.out
      0m32.550s nyata
      pengguna 0m32.466s
      sys 0m0.008s

  • std::atomic<int>:

    $ waktu ./a.out
      0m32.091s nyata
      pengguna 0m31.958s
      sys 0m0.012s


12
2017-10-30 11:23



Tebakan saya adalah ini adalah pertanyaan perangkat keras. Ketika Anda menulis volatile Anda memberi tahu compiler untuk tidak mengasumsikan apa pun tentang variabel tersebut tetapi seperti yang saya pahami, perangkat keras masih akan memperlakukannya sebagai variabel normal. Ini berarti bahwa variabel akan berada di cache sepanjang waktu. Ketika Anda menggunakan atom Anda menggunakan instruksi perangkat keras khusus yang mungkin berarti bahwa variabel tersebut diambil dari memori utama setiap kali digunakan. Perbedaan waktu konsisten dengan penjelasan ini.


2
2017-12-17 14:23