Mengapa prosesor memiliki 32 register?

52

Saya selalu bertanya-tanya mengapa prosesor berhenti di 32 register. Ini adalah bagian mesin yang tercepat, mengapa tidak membuat prosesor yang lebih besar dengan register yang lebih banyak? Bukankah itu berarti lebih sedikit pergi ke RAM?

Matt Capone
sumber
2
Saya kira melampaui titik tertentu semua variabel lokal Anda masuk ke dalam register. Data aktual yang Anda kerjakan mungkin terlalu besar
Niklas B.
14
Pengembalian berkurang. Jelas, register "lebih mahal" (dalam berbagai hal) daripada RAM atau kita hanya memiliki register 8GB.
David Richerby
5
Salah satu alasannya begitu cepat adalah karena tidak banyak dari mereka.
stackErr
5
Ada perbedaan antara berapa banyak register cpu memiliki total, dan berapa banyak yang dapat Anda gunakan sekaligus.
Thorbjørn Ravn Andersen
CPU dan GPU menyembunyikan latensi masing-masing dengan cache dan multithreading. Jadi, CPU memiliki beberapa register, sedangkan GPU memiliki puluhan ribu pada register. Lihat kertas survei saya pada file register GPU yang membahas semua trade-off dan faktor-faktor ini.
user984260

Jawaban:

82

Pertama, tidak semua arsitektur prosesor berhenti di 32 register. Hampir semua arsitektur RISC yang memiliki 32 register terekspos dalam set instruksi sebenarnya memiliki 32 register integer dan 32 register floating point lainnya (jadi 64). (Floating point "add" menggunakan register berbeda dari integer "add".) Arsitektur SPARC memiliki register windows. Pada SPARC Anda hanya dapat mengakses 32 register integer pada satu waktu, tetapi register bertindak seperti tumpukan dan Anda dapat mendorong dan pop register baru 16 sekaligus. Arsitektur Itanium dari HP / Intel memiliki 128 integer dan 128 register floating point yang terekspos dalam set instruksi. GPU modern dari NVidia, AMD, Intel, ARM, dan Imagination Technologies, semuanya memperlihatkan sejumlah besar register dalam file register mereka. (Saya tahu ini benar dari arsitektur NVidia dan Intel, saya tidak begitu akrab dengan set instruksi AMD, ARM dan Imagination, tapi saya pikir file register juga besar di sana.)

Kedua, sebagian besar mikroprosesor modern menerapkan pengubahan nama register untuk menghilangkan serialisasi yang tidak perlu yang disebabkan oleh kebutuhan untuk menggunakan kembali sumber daya, sehingga file register fisik yang mendasarinya dapat lebih besar (96, 128 atau 192 register pada beberapa mesin.) Ini (dan penjadwalan dinamis) menghilangkan beberapa perlu bagi kompiler untuk menghasilkan begitu banyak nama register yang unik, sambil tetap menyediakan file register yang lebih besar untuk penjadwal.

Ada dua alasan mengapa mungkin sulit untuk lebih meningkatkan jumlah register yang terekspos dalam set instruksi. Pertama, Anda harus dapat menentukan pengidentifikasi register dalam setiap instruksi. 32 register membutuhkan specifier register 5 bit, sehingga instruksi 3-alamat (umum pada arsitektur RISC) menghabiskan 15 dari 32 bit instruksi hanya untuk menentukan register. Jika Anda meningkatkannya menjadi 6 atau 7 bit, maka Anda akan memiliki lebih sedikit ruang untuk menentukan opcodes dan konstanta. GPU dan Itanium memiliki instruksi yang jauh lebih besar. Instruksi yang lebih besar dikenakan biaya: Anda perlu menggunakan lebih banyak memori instruksi, sehingga perilaku cache instruksi Anda kurang ideal.

Alasan kedua adalah waktu akses. Semakin besar Anda membuat memori semakin lambat untuk mengakses data dari itu. (Hanya dalam hal fisika dasar: data disimpan dalam ruang 2 dimensi, jadi jika Anda menyimpan bit, jarak rata-rata ke bit tertentu adalah .) File register hanyalah sebuah memori multi-porting kecil, dan salah satu kendala untuk membuatnya lebih besar adalah bahwa pada akhirnya Anda harus mulai mencatat mesin Anda lebih lambat untuk mengakomodasi file register yang lebih besar. Biasanya dalam hal kinerja total ini adalah kerugian. O ( nO(n)

Logika Pengembaraan
sumber
1
Saya akan menyebutkan 256 FPR SPARC64 VIIIfx dan 32 GPR non-jendela tambahan, yang diselesaikan dengan menambahkan instruksi Set XAR yang masing-masing menyediakan 13 bit untuk satu atau dua instruksi berikutnya. Itu ditargetkan pada HPC, sehingga jumlah register lebih mudah dimengerti. Saya juga akan tergoda untuk menjelaskan beberapa trade-off dan teknik yang terkait dengan lebih banyak register; tetapi Anda menunjukkan kebijaksanaan untuk menghindari jawaban yang lebih melelahkan (dan bahkan tidak lengkap).
Paul A. Clayton
2
Menambahkan sedikit pada manfaat berkurang dari lebih banyak register untuk kode "tujuan umum" mungkin bermanfaat, meskipun menemukan pengukuran yang bermakna tidak mudah. Saya pikir Mitch Alsup disebutkan di comp.arch bahwa memperluas x86 ke 32 register daripada 16 akan mendapatkan sekitar 3% dalam kinerja dibandingkan dengan (ISTR) 10-15% untuk ekstensi register 8 hingga 16 yang dipilih. Bahkan untuk ISA load-store, pergi ke 64 mungkin memberikan sedikit manfaat (setidaknya untuk kode GP saat ini). (BTW, GPU sering berbagi register di utas: mis., Satu utas dengan 250 utas meninggalkan total 16 utas untuk utas lainnya.)
Paul A. Clayton
Menarik untuk melihat bahwa manajemen lingkungan (maka konversi alfa), sering dikaitkan dengan bahasa tingkat tinggi, sebenarnya digunakan pada tingkat register.
babou
@ PaulA.Clayton Saya selalu berpikir bahwa IA-64 adalah arsitektur yang memiliki jumlah register ISA terbesar
phuclv
@ LưuVĩnhPhúc SPARC64 VIIIfx khusus untuk HPC. FYI, Am29k (diperkenalkan sekitar 1987-8 ) memiliki 64 GPR global dan 128 jendela yang lebih banyak GPR daripada Itanium (yang memang memiliki 8 register cabang dan register penghitungan putaran yang fungsinya akan di GPR di beberapa ISA lainnya).
Paul A. Clayton
16

Hanya dua alasan lagi untuk membatasi jumlah register:

  • Sedikit keuntungan yang diharapkan: CPU seperti model Intel / AMD x64 saat ini memiliki 32kByte dan lebih banyak cache L1-D, dan akses ke cache L1 biasanya hanya membutuhkan satu siklus clock (dibandingkan dengan sekitar seratus siklus siklus untuk RAM tunggal yang lengkap) mengakses). Jadi ada sedikit yang bisa diperoleh dari memiliki lebih banyak data dalam register dibandingkan dengan memiliki data dalam cache L1
  • Biaya komputasi tambahan: Memiliki lebih banyak register membuat overhead yang sebenarnya dapat membuat komputer lebih lambat:
    • Dalam lingkungan multitasking, pengalih tugas biasanya harus menyimpan konten semua register dari proses yang dibiarkan di memori, dan harus memuat semua proses yang akan dimasukkan. Semakin banyak register yang Anda miliki, semakin lama waktu yang dibutuhkan.
    • Demikian pula, dalam arsitektur tanpa jendela register, panggilan fungsi bertingkat menggunakan set register yang sama. Jadi fungsi A yang memanggil fungsi B menggunakan set register yang sama dengan B itu sendiri. Oleh karena itu, B harus menyimpan konten dari semua register yang digunakannya (yang masih memegang nilai-nilai A) dan harus menuliskannya kembali sebelum kembali (dalam beberapa konvensi panggilan itu adalah tugas A untuk menyimpan konten registernya sebelum memanggil B, tetapi overhead serupa). Semakin banyak register yang Anda miliki, semakin lama waktu yang dihemat ini, dan karenanya semakin mahal pemanggilan fungsi.
Robert Buchholz
sumber
Bagaimana cara kerjanya untuk cache L1 sehingga kita tidak memiliki masalah yang sama dengan register?
babou
4
Pada prosesor berkinerja tinggi L1 Dcache latensi lebih biasanya 3 atau 4 siklus (termasuk pembuatan alamat), misalnya, Haswell Intel memiliki 4 siklus latensi (tidak memiliki latensi register ketergantungan data, juga lebih mudah disembunyikan di dalam pipa). Dcache juga cenderung mendukung lebih sedikit akses per siklus (misalnya, 2 baca, 1 tulis untuk Haswell) daripada file register (misalnya, 4 baca, 6 tulis untuk Alpha 21264 yang mereplikasi file, 2 file dengan 4 baca lebih cepat dari 1 dengan 8).
Paul A. Clayton
@ PaulA.Clayton: Jika cache L1 memiliki latensi 3-4 siklus, itu akan menyarankan bahwa mungkin ada beberapa manfaat untuk memiliki misalnya beberapa set 64 kata memori siklus tunggal dengan ruang alamat 64 kata sendiri, dan instruksi "load / store direct" khusus, terutama jika ada cara untuk mendorong semua nilai bukan nol diikuti dengan kata yang mengatakan kata-kata mana yang bukan nol, dan kemudian cara untuk mengembalikannya (memberi nol pada register yang tidak muncul) . Banyak metode memiliki antara 16 dan 60 kata variabel lokal, jadi memotong waktu akses bagi mereka yang dari 3-4 siklus menjadi satu akan tampak membantu.
supercat
@supercat Berbagai ide cache (dan global / TLS [mis., Knapsack]) telah disajikan dalam makalah akademis serta mekanisme seperti buffer tanda tangan ( PDF ) Penggunaan aktual, tidak begitu banyak (tampaknya). Ini semakin akrab (jadi mungkin harus berakhir atau pergi ke tempat lain).
Paul A. Clayton
4

Banyak kode yang memiliki banyak akses memori (30% adalah angka tipikal). Dari itu, biasanya sekitar 2 / 3rds adalah akses baca dan 1 / 3rds adalah akses tulis. Ini bukan karena kehabisan register sebanyak mengakses array, mengakses variabel anggota objek dll.

HAS ini harus dilakukan dalam memori (atau cache data) karena bagaimana C / C ++ dibuat (semua yang Anda bisa dapatkan pointer harus memiliki alamat agar berpotensi disimpan dalam memori). Jika kompiler dapat menebak bahwa Anda tidak akan menulis ke variabel mau tak mau menggunakan trik pointer tidak langsung gila itu akan menempatkan mereka dalam register, dan ini berfungsi baik untuk variabel fungsi tetapi tidak untuk yang dapat diakses secara global (umumnya, semua yang keluar dari malloc ()) karena pada dasarnya tidak mungkin untuk menebak bagaimana keadaan global akan berubah.

Karena itu, kompiler tidak dapat melakukan apa pun dengan lebih dari 16 register penggunaan umum. Itulah sebabnya semua arsitek terkenal memiliki sebanyak itu (ARM memiliki 16).

MIPS dan RISC lainnya cenderung memiliki 32 karena tidak terlalu sulit untuk memiliki banyak register - biayanya cukup rendah sehingga sedikit "mengapa tidak?". Lebih dari 32 sebagian besar tidak berguna dan memiliki kelemahan membuat file register lebih lama diakses (masing-masing dua kali lipat dalam jumlah register berpotensi menambah lapisan multiplexer tambahan yang menambah sedikit keterlambatan ...). Ini juga membuat instruksi sedikit lebih lama rata-rata - yang berarti bahwa ketika menjalankan jenis program yang bergantung pada bandwidth memori instruksi, register tambahan Anda sebenarnya memperlambat Anda!

Jika CPU Anda tidak berurutan dan tidak melakukan pengubahan nama register dan Anda mencoba melakukan banyak operasi per siklus (lebih dari 3), maka secara teori Anda membutuhkan lebih banyak register karena jumlah operasi Anda per siklus meningkat. Inilah sebabnya mengapa Itanium memiliki begitu banyak register! Namun dalam praktiknya, selain dari angka-angka-mengambang-titik atau kode berorientasi SIMD (yang sangat bagus di Itanium), sebagian besar kode akan memiliki banyak memori yang dibaca / ditulis dan melompat yang membuat mimpi ini lebih dari-3 ops per siklus tidak mungkin (terutama dalam perangkat lunak berorientasi server seperti database, kompiler, eksekusi bahasa tingkat tinggi seperti javascript, emulasi dll ...). Inilah yang menenggelamkan Itanium.

Itu semua bermuara pada perbedaan antara perhitungan dan eksekusi!

Hubert Lamontagne
sumber
2

Siapa yang memberi tahu Anda bahwa prosesor selalu memiliki 32 register? x86 memiliki 8, ARM 32-bit dan x86_64 memiliki 16, IA-64 memiliki 128, dan banyak lagi angka lainnya. Anda dapat melihatnya di sini . Bahkan MIPS, PPC atau arsitektur apa pun yang memiliki 32 register tujuan umum dalam set instruksi, jumlahnya jauh lebih besar dari 32 karena selalu ada register flag (jika ada), register kontrol ... tidak termasuk register yang diganti nama dan register perangkat keras

Semuanya ada harganya. Semakin besar jumlah register, semakin banyak pekerjaan yang Anda miliki saat melakukan pengalihan tugas, semakin banyak ruang yang Anda butuhkan dalam pengkodean instruksi. Jika Anda memiliki lebih sedikit register, Anda tidak perlu menyimpan dan mengembalikan banyak ketika menelepon dan kembali dari fungsi atau beralih tugas dengan imbalan kurangnya register dalam beberapa kode komputasi-luas

Selain itu, semakin besar file register, semakin mahal dan kompleks. SRAM adalah RAM tercepat dan termahal sehingga hanya digunakan dalam cache CPU. Tapi itu masih jauh lebih murah dan memakan waktu lebih sedikit daripada file register dengan kapasitas yang sama.

phuclv
sumber
2

Sebagai contoh, prosesor Intel yang khas memiliki "integer" 16 resmi dan 16 register vektor. Namun pada kenyataannya, ada banyak lagi: Prosesor menggunakan "register renaming". Jika Anda memiliki instruksi reg3 = reg1 + reg2, Anda akan memiliki masalah jika instruksi lain menggunakan reg3 belum selesai - Anda tidak dapat menjalankan instruksi baru jika menimpa reg3 sebelum telah dibaca oleh instruksi sebelumnya.

Karena itu ada sekitar 160 register nyata . Jadi instruksi sederhana di atas diubah menjadi "regX = reg1 + reg2, dan ingat bahwa regX berisi reg3". Tanpa mengganti nama register, eksekusi yang tidak benar akan benar-benar mati.

gnasher729
sumber
1

Saya bukan seorang insinyur listrik, tetapi saya pikir kemungkinan lain untuk alasan membatasi jumlah register, adalah routing. Ada jumlah unit aritmatika yang terbatas, dan mereka harus dapat mengambil input dari setiap register, dan output ke setiap register. Ini terutama benar ketika Anda memiliki program pipelined yang dapat menjalankan banyak instruksi per siklus.

Versi sederhana dari ini akan memiliki kompleksitas , membuat peningkatan jumlah register tidak dapat diabaikan, atau membutuhkan perancangan ulang perutean ke sesuatu yang jauh lebih rumit untuk merutekan semuanya dengan kompleksitas yang lebih baik.O(n2)

Saya mendapat ide untuk jawaban ini dari menonton beberapa pembicaraan Ivan Godard pada CPU Mill. Bagian dari inovasi Mill CPU adalah bahwa Anda tidak dapat menampilkan ke register sewenang-wenang - semua output didorong ke tumpukan register atau "sabuk", yang dengan demikian mengurangi masalah perutean, karena Anda selalu tahu kemana output akan pergi. Perhatikan bahwa mereka masih memiliki masalah perutean untuk mendapatkan register input ke unit aritmatika.

Lihat Arsitektur CPU Mill - the Belt (2 dari 9) untuk pernyataan masalah, dan solusi Mill.

Realz Slaw
sumber
"Mereka harus dapat mengambil input dari setiap register, dan output ke setiap register." - Saya berharap ini biasanya diterapkan dengan bus, tidak harus ada koneksi terpisah ke ALU (s) untuk setiap register.
user253751
1
@immibis: Jika Anda ingin memindahkan data dalam 300 picoseconds, bus tidak akan melakukannya. Dan jika Anda ingin memindahkan banyak data (misalnya untuk melakukan tiga instruksi dengan dua operan dan satu hasil masing-masing dalam siklus yang sama), bus akan benar-benar tidak berfungsi.
gnasher729
0

Adapun MIPS ISA, Hennessy and Patterson, Computer Organisation and Design edisi ke-4 hlm. 176, jawab pertanyaan spesifik ini secara langsung:

Lebih kecil lebih cepat. Keinginan untuk kecepatan adalah alasan bahwa MIPS memiliki 32 register daripada banyak lagi.

Olsonis
sumber