biaya operasi atom

92

Berapa biaya operasi atom (salah satu dari perbandingan-dan-tukar atau penambahan / pengurangan atom)? Berapa siklus yang dikonsumsi? Apakah akan menjeda prosesor lain di SMP atau NUMA, atau akan memblokir akses memori? Apakah itu akan membersihkan buffer pemesanan ulang di CPU yang rusak?

Efek apa yang akan terjadi pada cache?

Saya tertarik dengan CPU modern dan populer: x86, x86_64, PowerPC, SPARC, Itanium.

osgx
sumber
@Jason S, Apa saja. Perbedaan antara cas dan atomic inc / dec dapat diabaikan.
osgx
2
Operasi atom pada x86 menjadi lebih lambat karena lebih banyak pertikaian ditempatkan pada alamat memori. Saya yakin secara umum mereka berada di sekitar urutan besarnya lebih lambat daripada operasi yang tidak terkunci, tetapi jelas ini akan bervariasi tergantung pada operasi, perselisihan dan hambatan memori yang digunakan.
Stephen Nutt
hmmm. menulis tampaknya atom pada x86. 'Memahami Kernel Linux' -> spin_unlock
osgx
Sebuah 32bit menulis adalah atom di Java, yaitu itu adalah atom yang mudah dibawa (tetapi tidak memiliki semantik penghalang memori, jadi ini seringkali tidak cukup untuk pointer). Menambahkan 1 biasanya tidak atomic, kecuali Anda menambahkan awalan LOCK. Tentang kernel Linux, tidak perlu melihat spin_unlock. Lihat, dalam rilis saat ini, arch / x86 / include / asm / atomic_32.h (dulu termasuk / asm-i386 / atomic.h).
Blaisorblade
@Blaisorblade, JAva tidak ada di sini. Berapa biaya operasi TERKUNCI?
osgx

Jawaban:

61

Saya telah mencari data aktual selama beberapa hari terakhir, dan tidak menemukan apa pun. Namun, saya melakukan beberapa penelitian, yang membandingkan biaya operasi atom dengan biaya kehilangan cache.

Biaya awalan x86 LOCK, (termasuk lock cmpxchguntuk CAS atom), sebelum PentiumPro (seperti yang dijelaskan dalam dokumen), adalah akses memori (seperti cache miss), + menghentikan operasi memori oleh prosesor lain, + perselisihan apa pun dengan prosesor lain mencoba MENGUNCI bus. Namun, sejak PentiumPro, untuk memori Writeback normal yang dapat di-cache (semua memori yang ditangani aplikasi, kecuali Anda berbicara langsung dengan perangkat keras), alih-alih memblokir semua operasi memori, hanya baris cache yang relevan yang diblokir (berdasarkan tautan dalam jawaban @ osgx ) .

yaitu penundaan inti menjawab bagian MESI dan permintaan RFO untuk saluran tersebut sampai setelah bagian penyimpanan dari lockoperasi ed yang sebenarnya . Ini disebut "kunci cache", dan hanya mempengaruhi satu baris cache itu. Core lain dapat memuat / menyimpan atau bahkan meng-CAS saluran lain pada saat yang bersamaan.


Sebenarnya, kasus CAS bisa menjadi lebih rumit, seperti yang dijelaskan di halaman ini , tanpa pengaturan waktu tetapi dengan deskripsi yang mendalam oleh teknisi yang dapat dipercaya. (Setidaknya untuk kasus penggunaan normal di mana Anda melakukan pemuatan murni sebelum CAS yang sebenarnya.)

Sebelum membahas terlalu banyak detail, saya akan mengatakan bahwa operasi TERKUNCI menghabiskan satu cache yang hilang + kemungkinan pertikaian dengan prosesor lain pada cacheline yang sama, sementara CAS + beban sebelumnya (yang hampir selalu diperlukan kecuali pada mutex, di mana Anda selalu CAS 0 dan 1) dapat menyebabkan kehilangan dua cache.

Dia menjelaskan bahwa beban + CAS di satu lokasi sebenarnya dapat menyebabkan kehilangan dua cache, seperti Load-Linked / Store-Conditional (lihat di sana untuk yang terakhir). Penjelasannya bergantung pada pengetahuan tentang protokol koherensi cache MESI . Ini menggunakan 4 status untuk cacheline: M (odified), E (xclusive), S (hared), I (nvalid) (dan oleh karena itu disebut MESI), dijelaskan di bawah jika diperlukan. Skenario tersebut, dijelaskan, adalah sebagai berikut:

  • LOAD menyebabkan kehilangan cache - cache yang relevan dimuat dari memori dalam status Bersama (yaitu prosesor lain masih diizinkan untuk menyimpan cache tersebut dalam memori; tidak ada perubahan yang diizinkan dalam status ini). Jika lokasinya ada di memori, cache miss ini akan dilewati. Kemungkinan biaya: 1 cache hilang. (dilewati jika cacheline dalam status Dibagikan, Eksklusif, atau Dimodifikasi, yaitu data ada di cache L1 CPU ini).
  • program menghitung nilai baru untuk disimpan,
  • dan menjalankan instruksi CAS atom.
    • Itu harus menghindari modifikasi bersamaan, jadi itu harus menghapus salinan cacheline dari cache CPU lain, untuk memindahkan cacheline ke status Eksklusif. Kemungkinan biaya: 1 cache hilang. Ini tidak diperlukan jika sudah dimiliki secara eksklusif, yaitu dalam status Eksklusif atau Dimodifikasi. Di kedua status, tidak ada CPU lain yang menahan cacheline, tetapi dalam status Eksklusif belum diubah (belum).
    • Setelah komunikasi ini, variabel diubah dalam cache lokal CPU kita, yang mana pada saat itu variabel tersebut dapat dilihat secara global oleh semua CPU lain (karena cache mereka koheren dengan milik kita). Ini pada akhirnya akan ditulis ke memori utama sesuai dengan algoritma biasa.
    • Prosesor lain yang mencoba membaca atau memodifikasi variabel itu terlebih dahulu harus mendapatkan cache tersebut dalam mode Bersama atau Eksklusif, dan untuk melakukannya akan menghubungi prosesor ini dan menerima versi cache yang diperbarui. Operasi TERKUNCI, sebaliknya, hanya dapat menyebabkan hilangnya cache (karena cache akan diminta langsung dalam status Eksklusif).

Dalam semua kasus, permintaan cacheline dapat dihentikan oleh pemroses lain yang sudah memodifikasi data.

Blaisorblade
sumber
mengapa mengubah status pada CPU lain dikenakan biaya karena 1 cache tidak ada?
osgx
1
Karena itu komunikasi di luar CPU, dan dengan demikian lebih lambat daripada mengakses cache. Meskipun cache miss harus lolos dari CPU lain. Sebenarnya, mungkin saja berbicara dengan CPU lain lebih cepat daripada berbicara dengan memori, jika interkoneksi langsung digunakan, seperti AMD Hypertransport (sejak dulu), atau Intel QuickPath Interconnect dari Intel, pada prosesor Xeon terbaru. berdasarkan Nehalem. Jika tidak, komunikasi dengan CPU lain berlangsung di FSB yang sama dengan yang untuk memori. Cari HyperTransport dan Front Side Bus di Wikipedia untuk info lebih lanjut.
Blaisorblade
Wow, tidak pernah terpikir bahwa miliknya begitu mahal - cache miss bisa menjadi beberapa ribu siklus.
Lothar
2
Betulkah? Angka yang biasa saya gunakan adalah: seratus siklus untuk cache yang terlewat, dan ribuan siklus untuk sakelar konteks / hak istimewa (termasuk syscall).
Blaisorblade
1
Cache miss bukanlah beberapa ribu siklus! Ini tentang 100ns, yang biasanya 300-350 siklus CPU ....
user997112
37

Saya melakukan beberapa profil dengan pengaturan berikut: Mesin uji (AMD Athlon64 x2 3800+) di-boot, dialihkan ke mode panjang (interupsi dinonaktifkan) dan instruksi yang diinginkan dijalankan dalam satu lingkaran, 100 iterasi dibuka gulungan dan 1.000 siklus loop. Badan loop disejajarkan dengan 16 byte. Waktu diukur dengan instruksi rdtsc sebelum dan sesudah loop. Selain itu, sebuah dummy loop tanpa instruksi apa pun dijalankan (yang mengukur 2 siklus per iterasi loop dan 14 siklus untuk sisanya) dan hasilnya dikurangi dari hasil waktu pembuatan profil instruksi.

Instruksi berikut diukur:

  • " lock cmpxchg [rsp - 8], rdx" (keduanya cocok perbandingan dan tidak cocok),
  • " lock xadd [rsp - 8], rdx",
  • " lock bts qword ptr [rsp - 8], 1"

Dalam semua kasus, waktu yang diukur adalah sekitar 310 siklus, kesalahannya sekitar +/- 8 siklus

Ini adalah nilai untuk eksekusi berulang pada memori (cache) yang sama. Dengan cache tambahan yang hilang, waktunya jauh lebih tinggi. Ini juga dilakukan dengan hanya satu dari 2 inti yang aktif, jadi cache dimiliki secara eksklusif, dan tidak diperlukan sinkronisasi cache.

Untuk mengevaluasi biaya instruksi terkunci pada cache miss, saya menambahkan wbinvldinstruksi sebelum instruksi terkunci dan menambahkan wbinvldplus an add [rsp - 8], raxke dalam loop perbandingan. Dalam kedua kasus biayanya sekitar 80.000 siklus per pasangan instruksi! Dalam kasus bts kunci perbedaan waktu sekitar 180 siklus per instruksi.

Perhatikan bahwa ini adalah throughput timbal balik, tetapi karena operasi yang dikunci adalah operasi serialisasi, mungkin tidak ada perbedaan pada latensi.

Kesimpulan: operasi terkunci itu berat, tapi cache miss bisa jauh lebih berat. Juga: operasi yang terkunci tidak menyebabkan kehilangan cache. Ini hanya dapat menyebabkan lalu lintas sinkronisasi cache, jika cache tidak dimiliki secara eksklusif.

Untuk mem-boot mesin, saya menggunakan FreeLdr versi x64 dari proyek ReactOS. Berikut kode sumber asm:

#define LOOP_COUNT 1000
#define UNROLLED_COUNT 100

PUBLIC ProfileDummy
ProfileDummy:

    cli

    // Get current TSC value into r8
    rdtsc
    mov r8, rdx
    shl r8, 32
    or r8, rax

    mov rcx, LOOP_COUNT
    jmp looper1

.align 16
looper1:

REPEAT UNROLLED_COUNT
    // nothing, or add something to compare against
ENDR

    dec rcx
    jnz looper1

    // Put new TSC minus old TSC into rax
    rdtsc
    shl rdx, 32
    or rax, rdx
    sub rax, r8

    ret

PUBLIC ProfileFunction
ProfileFunction:

    cli

    rdtsc
    mov r8, rdx
    shl r8, 32
    or r8, rax
    mov rcx, LOOP_COUNT

    jmp looper2

.align 16
looper2:

REPEAT UNROLLED_COUNT
    // Put here the code you want to profile
    // make sure it doesn't mess up non-volatiles or r8
    lock bts qword ptr [rsp - 8], 1
ENDR

    dec rcx
    jnz looper2

    rdtsc
    shl rdx, 32
    or rax, rdx
    sub rax, r8

    ret
Timo
sumber
Terima kasih! Dapatkah Anda mempublikasikan kode pengujian Anda atau menguji sendiri Core2 / Core i3 / i5 / i7? Apakah semua inti diinisialisasi dalam pengaturan pengujian Anda?
osgx
Saya menambahkan kode sumber. Hanya satu inti yang diinisialisasi. Ingin sekali melihat hasil dari mesin lain.
Timo
CLFLUSH seharusnya menjadi cara yang jauh lebih ringan untuk membersihkan baris cache daripada WBINVD dari seluruh cache. WBINVD akan membersihkan cache instruksi juga, menyebabkan cache tambahan hilang.
Peter Cordes
Mungkin menarik untuk menguji kasus baris cache menjadi panas dalam status Bersama. Anda dapat mewujudkannya dengan meminta utas lain membacanya dengan beban murni.
Peter Cordes
4

Pada SMP berbasis bus, prefiks atomik LOCKmenegaskan (menghidupkan) sinyal kabel bus LOCK#. Ini akan melarang cpus / perangkat lain di bus untuk menggunakannya.

Buku Ppro & P2 http://books.google.com/books?id=3gDmyIYvFH4C&pg=PA245&dq=lock+instruction+pentium&lr=&ei=_E61S5ehLI78zQSzrqwI&cd=1#v=onepage&q=lock%20instruction%20pentium&f=46 halaman palsu

Instruksi yang dikunci adalah serialisasi, operasi sinkronisasi .... / about RMW tidak berurutan / terkunci RMW / read-modifikasikan-tulis = atomic itu sendiri / instruksi memastikan bahwa prosesor akan menjalankan semua instruksi sebelum instruksi terkunci sebelum mengeksekusinya. / about namun belum menghapus penulisan / itu memaksa semua tulisan yang diposting di dalam prosesor untuk di-flush ke memori eksternal sebelum menjalankan instruksi berikutnya.

/ about SMP / semaphore ada dalam cache dalam status S ... mengeluarkan transaksi baca dan batal untuk 0 byte tanggal (ini adalah kill / salinan bersama dari baris cache di CPU yang berdekatan /)

osgx
sumber