Bagaimana cache bisa secepat itu?


37

Berikut ini adalah screenshot dari tolok ukur cache:

Hasil benchmark Cache & Memory AIDA64

Dalam benchmark, kecepatan baca cache L1 adalah sekitar 186 GB / s, dengan latensi sekitar 3-4 siklus clock. Bagaimana kecepatan seperti itu bahkan dicapai?

Pertimbangkan memori di sini: kecepatan maksimum teoritis adalah 665 MHz (frekuensi memori) x 2 (kecepatan data ganda) x 64 bit (lebar bus) yaitu sekitar 10,6 GB / s, yang lebih dekat dengan nilai patokan 9,6 GB / s .

Tetapi dengan cache L1, bahkan jika kita bisa membaca di setiap siklus dengan prosesor pada frekuensi maksimum (3 GHz), kita akan membutuhkan sekitar 496 jalur data untuk mencapai throughput yang terdengar tidak realistis. Ini berlaku untuk cache lainnya juga.

Apa yang saya lewatkan? Bagaimana kita menghitung throughput cache dari parameternya?


14
sudahkah Anda mempertimbangkan betapa kecilnya cache L1,2,3 & secara merata di mana ia berada secara fisik. Kiat, Anda tidak perlu khawatir dengan standar bus jika Anda memiliki seluruh chip
JonRB

2
Juga: Apakah tolok ukur cukup tahu tentang apa yang dilakukannya untuk memastikan beberapa data yang diuji dengan tidak disimpan langsung di dalam register?
rackandboneman

7
@rackandboneman: AIDA64 adalah patokan yang sangat disegani, bukan sesuatu yang baru saja diretas oleh seseorang di C dan membiarkan kompiler mengoptimalkan beberapa muatan! Saya akan berasumsi bagian microbenchmark ditulis dalam perakitan, dengan versi SSE atau AVX.
Peter Cordes

1
@ Peter Cordes jawaban yang memuaskan - untuk pertanyaan yang diperlukan.
rackandboneman

1
Hanya untuk menempatkan pemikiran dalam perspektif fisik: dalam 1,4 nanodetik cahaya bergerak sekitar satu setengah kaki. Itu berarti bahwa jika cache terletak di sisi lain motherboard, latensi seperti itu dapat merusak relativitas. Atau menjadi kesalahan pengukuran .
Arthur

Jawaban:


35

CPU ini memiliki ...

2 core Sebuah instruksi 32-KB dan cache level pertama data (L1) 32-KB untuk setiap core

Karena ada dua inti, kita dapat mengharapkan patokan menjalankan dua utas secara paralel. Situs web mereka memberikan sedikit informasi, tetapi jika kita lihat di sini , CPU dengan core lebih banyak tampaknya memberikan throughput L1 yang lebih tinggi. Jadi saya pikir apa yang ditampilkan adalah total throughput dengan semua core bekerja secara paralel. Jadi, untuk CPU Anda, kami harus membaginya dengan dua untuk satu inti dan satu cache:

Read   93 GB/s
Write  47 GB/s
Copy   90 GB/s

Sekarang, fakta "menyalin" 2x lebih cepat dari "menulis" sangat mencurigakan. Bagaimana bisa menyalin lebih cepat daripada yang bisa ditulis? Saya akan bertaruh bahwa apa yang ditampilkan oleh benchmark sebagai "copy" adalah jumlah dari read + write throughput, dan dalam hal ini keduanya akan membaca dan menulis pada 45 GB / s, tetapi menampilkan 90, karena itu adalah benchmark, dan siapa yang percaya tolok ukur? Jadi mari kita abaikan "copy".

Read   93 GB/s => 30 bytes/clock
Write  47 GB/s => 15 bytes/clock

Sekarang, satu register 128-bit adalah 16 byte, cukup dekat, sehingga sepertinya cache ini dapat melakukan dua pembacaan 128-bit dan satu penulisan per jam.

Inilah tepatnya yang Anda ingin benar-benar merampingkan instruksi penguraian angka SSE: dua membaca dan satu menulis per siklus.

Ini kemungkinan besar akan diimplementasikan dengan banyak jalur data paralel, yang merupakan cara biasa untuk mengangkut banyak data dengan sangat cepat di dalam sebuah chip.


4
Pada halaman 55 dokumen @ tautan retas sebelahnya menyatakan "Secara internal, akses hingga 16 byte. [...] Dua operasi pemuatan dan satu operasi toko dapat ditangani setiap siklus". Itu menjelaskan mengapa membaca dua kali lebih cepat - ia dapat melakukan dua membaca dalam operasi yang sama sementara juga melakukan satu penulisan.
Tom Carpenter

2
Ya, jelas menghitung copy BW = baca dan tulis. Tampaknya sama validnya dengan alternatifnya, karena sangat penting bahwa membaca dan menulis dapat dieksekusi secara paralel. Perhatikan bahwa nomor OP untuk L2 / L3 memiliki salinan tidak jauh lebih tinggi daripada tulis, dan lebih rendah untuk memori. Bus memori DDR3 tidak full-duplex: jalur data yang sama diperlukan untuk membaca dan menulis. (Untuk lebih lanjut tentang x86 memcpy / memset bandwidth dengan toko NT vs toko biasa, lihat stackoverflow.com/questions/43343231/... ).
Peter Cordes

6
Anda menduga bahwa IvyBridge dapat melakukan 2 kali membaca dan 1 menulis dalam siklus jam yang sama. Anda memang benar, tetapi hanya dalam keadaan yang sangat terbatas. IvB hanya memiliki 2 port AGU, jadi biasanya itu terbatas pada 2 ops memori per jam, hingga salah satunya adalah toko . Tapi 256b AVX memuat / menyimpan mengambil 2 siklus untuk mengeksekusi di pelabuhan memuat / menyimpan, sementara hanya membutuhkan AGU di siklus pertama. Jadi uop store-address dapat berjalan pada port 2/3 selama siklus ke-2 dari beban 256b tanpa biaya bandwidth beban apa pun. (Simpan-data uops dijalankan pada port 4.) Sumber: agner.org/optimize microarch pdf
Peter Cordes

2
AMD Bulldozer-family atau Ryzen CPU akan memberi Anda angka baca = 2x tulis yang sama, tetapi mereka benar-benar terbatas pada 2 ops memori per jam (hingga satu dapat berupa penulisan) tanpa celah. baca / tulis / salin tidak mendeteksi perbedaan, tetapi Triad dapat ( a[i] = b[i] + c[i]). BTW, Intel Haswell dan nantinya memiliki store-AGU pada port 7 yang dapat menangani mode pengalamatan sederhana (tidak diindeks), sehingga mereka dapat menjalankan 2 load + 1 uops store per jam. (Dan jalur data ke L1D adalah 256b, sehingga menggandakan bandwidth L1D.) Lihat tulisan David Kanter: realworldtech.com/haswell-cpu/5
Peter Cordes

1
@AliChen: OP secara eksplisit menyebutkan latensi penggunaan beban 4 siklus IvyBridge tepat setelah bandwidth, sebelum bertanya bagaimana bisa begitu cepat.
Peter Cordes

27

Jawaban @ peufeu menunjukkan bahwa ini adalah bandwidth agregat seluruh sistem. L1 dan L2 adalah cache pribadi per-inti dalam keluarga Intel Sandybridge, sehingga jumlahnya 2x apa yang dapat dilakukan oleh satu inti. Tapi itu masih membuat kita dengan bandwidth yang sangat tinggi, dan latensi rendah.

Cache L1D dibangun tepat ke inti CPU, dan sangat erat dengan unit eksekusi beban (dan buffer toko) . Demikian pula, cache L1I tepat di sebelah instruksi mengambil / mendekodekan bagian inti. (Saya sebenarnya belum melihat floorplan silikon Sandybridge, jadi ini mungkin tidak benar secara harfiah. Masalah / mengganti nama bagian dari front-end mungkin lebih dekat dengan "L0" cache cache yang diterjemahkan, yang menghemat daya dan memiliki bandwidth yang lebih baik dari pada decoder.)

Tetapi dengan L1 cache, bahkan jika kita bisa membaca di setiap siklus ...

Kenapa berhenti di situ? Intel sejak Sandybridge dan AMD sejak K8 dapat mengeksekusi 2 beban per siklus. Tembolok multi-port dan TLB adalah suatu hal.

Tulisan mikroarsitektur Sandybridge milik David Kanter memiliki diagram yang bagus (yang juga berlaku untuk CPU IvyBridge Anda):

("Unified scheduler" menahan ALU dan memory uops menunggu input mereka siap, dan / atau menunggu port eksekusi mereka. (Mis. vmovdqa ymm0, [rdi]Menerjemahkan ke load uop yang harus menunggu rdijika sebelumnya add rdi,32belum dieksekusi, untuk contoh). Intel menjadwalkan uops ke port pada masalah / mengubah nama waktu . Diagram ini hanya menunjukkan port eksekusi untuk memori uops, tetapi ALU yang tidak dieksekusi juga bersaing untuk itu. Tahap masalah / ganti nama menambahkan uops ke ROB dan penjadwal Mereka tetap berada di ROB hingga pensiun, tetapi hanya dalam penjadwal hingga mengirim ke port eksekusi (Ini adalah terminologi Intel; orang lain menggunakan masalah dan mengirim berbeda)). AMD menggunakan penjadwal terpisah untuk integer / FP, tetapi mode pengalamatan selalu menggunakan register integer

Diagram memori SnB David Kanter

Seperti yang ditunjukkan, hanya ada 2 port AGU (unit pembangkit alamat, yang mengambil mode pengalamatan seperti [rdi + rdx*4 + 1024]dan menghasilkan alamat linear). Ia dapat menjalankan 2 ops memori per jam (masing-masing 128b / 16 byte), hingga salah satunya menjadi toko.

Tapi ada triknya: SnB / IvB menjalankan 256b AVX memuat / menyimpan sebagai uop tunggal yang membutuhkan 2 siklus dalam port load / store, tetapi hanya membutuhkan AGU pada siklus pertama. Itu memungkinkan uop store-address dijalankan pada AGU pada port 2/3 selama siklus kedua tanpa kehilangan throughput beban. Jadi dengan AVX (yang Intel Pentium / Celeron CPU tidak mendukung: /), SnB / IvB dapat (secara teori) mempertahankan 2 beban dan 1 toko per siklus.

CPU IvyBridge Anda adalah die-shrink dari Sandybridge (dengan beberapa perbaikan mikroarsitektur, seperti mov-elimination , ERMSB (memcpy / memset), dan prefetching perangkat keras halaman berikutnya). Generasi setelah itu (Haswell) menggandakan bandwidth L1D per-jam dengan memperluas jalur data dari unit eksekusi ke L1 dari 128b menjadi 256b sehingga beban AVX 256b dapat mempertahankan 2 per jam. Itu juga menambahkan port AGU toko tambahan untuk mode pengalamatan sederhana.

Puncak throughput Haswell / Skylake adalah 96 byte dimuat + disimpan per jam, tetapi manual optimasi Intel menunjukkan bahwa throughput berkelanjutan Skylake rata-rata (masih dengan asumsi tidak ada kehilangan L1D atau TLB) adalah ~ 81B per siklus. (Lingkaran bilangan skalar dapat menopang 2 beban + 1 toko per jam menurut pengujian saya di SKL, menjalankan 7 (domain tidak terpakai) uops per jam dari 4 domain domain menyatu. Tetapi agak melambat dengan operan 64-bit alih-alih 32-bit, jadi ternyata ada beberapa batasan sumber daya mikroarsitektur dan itu bukan hanya masalah penjadwalan toko-alamat uops ke port 2/3 dan mencuri siklus dari banyak.)

Bagaimana kita menghitung throughput cache dari parameternya?

Anda tidak bisa, kecuali parameternya menyertakan angka throughput praktis. Seperti disebutkan di atas, bahkan Skylake's L1D tidak bisa mengimbangi unit eksekusi load / store untuk 256b vektor. Meskipun dekat, dan bisa untuk bilangan bulat 32-bit. (Tidak masuk akal untuk memiliki lebih banyak unit muat daripada cache membaca port, atau sebaliknya. Anda hanya akan meninggalkan perangkat keras yang tidak pernah dapat sepenuhnya digunakan. Perhatikan bahwa L1D mungkin memiliki port tambahan untuk mengirim / menerima saluran ke / dari core lain, serta untuk membaca / menulis dari dalam inti.)

Hanya dengan melihat lebar bus data dan jam tidak memberi Anda keseluruhan cerita. Bandwidth L2 dan L3 (dan memori) dapat dibatasi oleh jumlah kesalahan luar biasa yang dapat dilacak L1 atau L2 . Bandwidth tidak dapat melebihi latensi * max_concurrency, dan chip dengan L3 latensi lebih tinggi (seperti Xeon banyak-inti) memiliki bandwidth L3 inti-tunggal jauh lebih sedikit daripada CPU dual / quad core dari mikroarsitektur yang sama. Lihat bagian "platform terikat latensi" pada jawaban SO ini . CPU Sandybridge-family memiliki 10 buffer line-fill untuk melacak kesalahan L1D (juga digunakan oleh toko NT).

(L3 / memori bandwidth agregat dengan banyak core aktif sangat besar pada Xeon besar, tetapi kode single-threaded melihat bandwidth lebih buruk daripada pada quad core pada kecepatan clock yang sama karena lebih banyak core berarti lebih banyak pemberhentian di ring bus, dan dengan demikian lebih tinggi latensi L3.)


Latensi cache

Bagaimana kecepatan seperti itu bahkan dicapai?

Latensi penggunaan cache 4 siklus L1D cukup menakjubkan , terutama mengingat bahwa ia harus dimulai dengan mode pengalamatan seperti [rsi + 32], sehingga harus melakukan penambahan sebelum bahkan memiliki alamat virtual . Maka harus menerjemahkannya ke fisik untuk memeriksa tag cache untuk kecocokan.

(Mengatasi mode selain [base + 0-2047]mengambil siklus tambahan pada Intel Sandybridge-family, jadi ada jalan pintas di AGU untuk mode pengalamatan sederhana (tipikal untuk kasus pengejaran pointer di mana latensi penggunaan beban rendah mungkin paling penting, tetapi juga umum pada umumnya) (Lihat manual pengoptimalan Intel , Sandybridge bagian 2.3.5.2 L1 DCache.) Ini juga mengasumsikan tidak ada pengesampingan segmen, dan alamat basis segmen 0, yang merupakan hal normal.)

Itu juga harus menyelidiki buffer toko untuk melihat apakah itu tumpang tindih dengan toko sebelumnya. Dan itu harus mencari tahu ini bahkan jika sebelumnya (dalam urutan program) toko-address uop belum dieksekusi, jadi alamat toko tidak diketahui. Tetapi mungkin ini bisa terjadi secara paralel dengan memeriksa hit L1D. Jika ternyata data L1D tidak diperlukan karena store-forwarding dapat menyediakan data dari buffer toko, maka itu bukan kerugian.

Intel menggunakan cache VIPT (Virtually Indexed Physically Tagged) seperti hampir semua orang, menggunakan trik standar untuk memiliki cache yang cukup kecil dan dengan asosiasi yang cukup tinggi sehingga berperilaku seperti cache PIPT (tanpa alias) dengan kecepatan VIPT (dapat mengindeks dalam sejajar dengan virtual-> TLB fisik lookup).

Cache Intel L1 adalah 32kiB, asosiatif 8 arah. Ukuran halaman adalah 4kiB. Ini berarti bit "index" (yang memilih 8 cara mana yang bisa men-cache setiap baris yang diberikan) semuanya di bawah halaman offset; yaitu bit alamat tersebut adalah offset ke halaman, dan selalu sama di alamat virtual dan fisik.

Untuk detail lebih lanjut tentang itu dan detail lain mengapa cache kecil / cepat bermanfaat / mungkin (dan berfungsi dengan baik ketika dipasangkan dengan cache lebih lambat yang lebih besar), lihat jawaban saya tentang mengapa L1D lebih kecil / lebih cepat daripada L2 .

Tembolok kecil dapat melakukan hal-hal yang akan terlalu mahal daya dalam tembolok yang lebih besar, seperti mengambil array data dari set pada saat yang sama dengan mengambil tag. Jadi, begitu pembanding menemukan tag mana yang cocok, itu hanya harus mux salah satu dari delapan baris cache 64-byte yang sudah diambil dari SRAM.

(Ini tidak sesederhana itu: Sandybridge / Ivybridge menggunakan cache L1D yang dibelokkan, dengan delapan bank potongan 16 byte. Anda bisa mendapatkan konflik bank-cache jika dua akses ke bank yang sama di baris cache yang berbeda coba dieksekusi dalam siklus yang sama. (Ada 8 bank, jadi ini bisa terjadi dengan alamat kelipatan 128 terpisah, yaitu 2 baris cache.)

IvyBridge juga tidak memiliki penalti untuk akses yang tidak selaras asalkan tidak melewati batas cache-line 64B. Saya kira itu menentukan bank mana yang harus diambil berdasarkan bit alamat rendah, dan mengatur perubahan apa pun yang perlu terjadi untuk mendapatkan 1 hingga 16 byte data yang benar.

Pada pemisahan cache-line, itu masih hanya satu uop, tetapi melakukan beberapa akses cache. Hukumannya masih kecil, kecuali pada split 4k. Skylake bahkan membuat pemecahan 4k cukup murah, dengan latensi sekitar 11 siklus, sama seperti split cache-line normal dengan mode pengalamatan yang kompleks. Tetapi throughput 4k-split secara signifikan lebih buruk daripada cl-split non-split.


Sumber :


1
Itu sangat jelas, lengkap dan ditulis dengan baik! +1!
next-hack

8

Pada CPU modern, memori cache berada tepat di sebelah CPU pada die (chip) yang sama , dibuat menggunakan SRAM yang jauh, jauh lebih cepat daripada DRAM yang digunakan untuk modul RAM pada PC.

Per unit memori (sedikit atau byte) SRAM jauh lebih mahal daripada DRAM. Jadi itu sebabnya DRAM digunakan di PC juga.

Tetapi karena SRAM dibuat dalam teknologi yang sama dengan CPU itu sendiri, itu secepat CPU. Juga, hanya ada bus internal (pada CPU) yang harus ditangani sehingga jika perlu 496 jalur lebar bus maka mungkin itu.


Terima kasih atas minat Anda. Saya telah melihat di beberapa buku yang menyatakan bahwa kecepatan akses register melebihi 300 GB / s dalam hal untuk prosesor 3 GHz throughput register adalah 100 B / siklus yang tidak mungkin karena register biasanya lebar 64/128 bit, mereka tidak bisa menghasilkan sebanyak itu. Inilah yang mengkhawatirkan saya. Apakah GB / sa cara yang tepat untuk mengekspresikan throughput.
Knight

3
@Knight perlu diingat bahwa IvB (seperti prosesor berkinerja tinggi) menjalankan beberapa instruksi per siklus, seperti 3 operasi ALU, 2 beban, dan 1 toko. Sebagian besar dari ini dapat mengambil 2 input (bahkan beban, untuk pengalamatan terindeks) dan beban bahkan mengambil 3. Itu 13 register pada masing-masing 8 byte, 104 byte (bisa jadi itu adalah kasus bahwa kombinasi epik tidak diperbolehkan, tetapi ada tidak ada indikasi bahwa itulah yang terjadi pada IvB, meskipun tidak dapat dipertahankan). Jika Anda juga mempertimbangkan register vektor, jumlah itu naik lebih jauh.
Harold

@harold: related: Haswell dan Skylake tampaknya memiliki batasan pada register reads per clock, meskipun itu mungkin ada di front-end dan tidak mempengaruhi ledakan eksekusi setelah beberapa input siap. Mungkin itu beberapa batas mikroarsitektur lainnya, tetapi saya menemukan kemacetan dalam kode yang harus dapat mempertahankan lebih banyak ops per jam. agner.org/optimize/blog/read.php?i=415#852 . Pada Haswell, skenario terbaik saya membaca ~ 6,5 integer register per clock cycle (berkelanjutan). Saya juga berhasil mendapatkan 7 uops per jam pengiriman / eksekusi di Skylake (toko adalah store-address + store-data).
Peter Cordes

@PeterCordes yang harus menjadi front-end bukan? IIRC itu juga masalah historis (PPro ke Core2) dan saya tidak yakin bagaimana bilangan pecahan masuk akal sebaliknya. Meskipun nomor saya agak sedikit kurang
harold

@harold: yeah, saya cukup yakin itu semacam hambatan front-end, mungkin dalam nama. Bottleneck register-read P6 ada pada register "dingin" yang harus dibaca dari file register permanen ke dalam ROB yang dipermasalahkan. Register yang dimodifikasi baru-baru ini masih dalam ROB, dan tidak ada hambatan pada itu. Saya tidak menyelidiki banyak dengan reg dingin dan panas pada HSW / SKL, karena untuk beberapa alasan saya tidak berpikir untuk membuat loop saya lebih besar dari 4 uops / idealnya 1c per iterasi. oops. IDK berapa banyak perbedaan yang ada antara penerusan vs membaca PRF (yang harus terjadi pada waktu eksekusi, bukan masalah / ganti nama).
Peter Cordes

4

Cache L1 adalah struktur memori yang cukup lebar. Arsitektur cache L1 dalam prosesor Intel dapat ditemukan di manual ini (disediakan oleh hack-berikutnya). Namun, interpretasi beberapa parameter tidak benar, "ukuran garis cache" bukan "lebar data", itu adalah ukuran blok serial akses data atom.

Tabel 2-17 (bagian 2.3.5.1) menunjukkan bahwa pada beban (dibaca), bandwidth cache adalah 2x16 = 32 Bytes per core per CYCLE . Ini saja memberikan bandwidth teoretis 96 Gb / s pada inti 3GHz. Tidak jelas apa yang dikutip dari laporan benchmark, sepertinya mengukur dua core yang bekerja secara paralel, sehingga menghasilkan 192 Gbps untuk dua core.


2

Gerbang penundaan apa? 10 picoseconds? Waktu siklus untuk seluruh operasi jaringan pipa adalah 333 picoseconds, dengan berbagai kegiatan decoding dan bus dan pengambilan data flip-flop sebelum siklus clock berikutnya dimulai.

Saya berharap aktivitas paling lambat dalam membaca cache sedang menunggu dataline untuk bergerak cukup jauh terpisah (kemungkinan ini adalah diferensial: satu referensi dan satu biaya aktual dari read-bit) bahwa pembanding / kait dapat clock untuk menerapkan positif- aksi umpan balik untuk mengubah tegangan kecil menjadi ayunan tegangan level logika rail-to-rail yang besar (sekitar 1 volt).


1
Perlu diingat bahwa latensi 4 siklus L1D mencakup pembangkitan alamat (untuk mode pengalamatan sederhana [reg + 0-2047]), dan pencarian TLB, dan perbandingan tag (asosiatif 8 arah), dan menempatkan byte up-to-16 dihasilkan yang tidak selaras ke dalam port output dari unit beban, untuk meneruskan ke unit eksekusi lainnya. Ini latensi 4c untuk loop seperti pointer-chasing mov rax, [rax].
Peter Cordes
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.