Bagaimana prosesor dirancang dan diproduksi: dasar-dasar arsitektur komputer

gambar

Kami menganggap prosesor sentral sebagai "otak" komputer, tetapi apa artinya sebenarnya? Apa sebenarnya yang terjadi di dalam miliaran transistor yang membuat komputer berfungsi? Dalam seri empat artikel baru kami, kami akan mempertimbangkan proses menciptakan arsitektur peralatan komputer dan berbicara tentang prinsip-prinsip operasinya.

Dalam seri ini kita akan berbicara tentang arsitektur komputer, desain papan prosesor, VLSI (integrasi skala sangat besar), pembuatan chip, dan tren masa depan di bidang teknologi komputer. Jika Anda tertarik untuk memahami detail prosesor, maka lebih baik untuk memulai studi dengan seri artikel ini.

Kita akan mulai dengan penjelasan tingkat tinggi tentang apa yang dilakukan prosesor dan bagaimana blok penyambung terhubung ke struktur yang berfungsi. Secara khusus, kami akan mempertimbangkan core prosesor, hirarki memori, prediksi cabang, dan banyak lagi. Pertama, kita perlu memberikan definisi sederhana tentang apa yang dilakukan CPU. Penjelasan paling sederhana: prosesor mengikuti serangkaian instruksi untuk melakukan operasi tertentu pada banyak data yang masuk. Misalnya, bisa membaca nilai dari memori, lalu menambahkannya ke nilai lain, dan akhirnya menyimpan hasilnya ke memori di alamat yang berbeda. Ini bisa menjadi sesuatu yang lebih rumit, misalnya, pembagian dua angka, jika hasil perhitungan sebelumnya lebih besar dari nol.

Program, seperti sistem operasi atau permainan, adalah sendiri urutan instruksi yang harus dijalankan CPU. Instruksi-instruksi ini dimuat dari memori dan dieksekusi dalam prosesor sederhana satu demi satu sampai program berakhir. Pengembang perangkat lunak menulis program dalam bahasa tingkat tinggi, seperti C ++ atau Python, tetapi prosesor tidak dapat memahaminya. Dia hanya mengerti satu dan nol, jadi kita perlu mewakili kode dalam format ini.


Program dikompilasi menjadi satu set instruksi tingkat rendah yang disebut bahasa assembly , yang merupakan bagian dari arsitektur set instruksi (ISA). Ini adalah serangkaian instruksi yang harus dipahami dan dijalankan oleh CPU. Beberapa ISA paling umum adalah x86, MIPS, ARM, RISC-V, dan PowerPC. Dengan cara yang sama bahwa sintaks untuk menulis fungsi dalam C ++ berbeda dari fungsi yang melakukan tindakan yang sama dengan Python, setiap ISA memiliki sintaksanya yang berbeda.

SPA ini dapat dibagi menjadi dua kategori utama: panjang tetap dan variabel. ISA RISC-V menggunakan instruksi dengan panjang tetap, yang berarti bahwa jumlah bit yang telah ditentukan dalam setiap instruksi menentukan tipe instruksi tersebut. Di x86, semuanya berbeda, ia menggunakan instruksi panjang variabel. Di x86, instruksi dapat dikodekan dengan cara yang berbeda dengan jumlah bit yang berbeda untuk bagian yang berbeda. Karena kerumitan ini, dekoder instruksi pada prosesor x86 biasanya merupakan bagian paling kompleks dari seluruh perangkat.

Instruksi dengan panjang tetap memberikan decoding sederhana karena struktur yang konstan, tetapi membatasi jumlah total instruksi yang dapat didukung oleh ISA. Sementara versi populer dari arsitektur RISC-V memiliki sekitar 100 instruksi dan semuanya adalah open source, arsitektur x86 adalah milik dan tidak ada yang tahu berapa banyak instruksi yang ada di dalamnya. Secara umum diyakini bahwa ada beberapa ribu instruksi x86, tetapi tidak ada yang mempublikasikan angka pastinya. Terlepas dari perbedaan antara ISA, pada kenyataannya mereka semua memiliki fungsi dasar yang sama.


Contoh beberapa instruksi RISC-V. Opcode di sebelah kanan adalah 7 bit panjang dan menentukan jenis instruksi. Selain itu, setiap instruksi berisi bit yang mendefinisikan register yang digunakan dan fungsi yang dilakukan. Jadi instruksi assembler dipecah menjadi kode biner sehingga prosesor memahaminya.

Sekarang kita siap untuk menyalakan komputer dan mulai menjalankan program. Pelaksanaan instruksi memiliki beberapa bagian dasar, yang terbagi dalam banyak tahapan prosesor.

Tahap pertama adalah transfer instruksi dari memori ke prosesor untuk memulai eksekusi. Pada langkah kedua, instruksi diterjemahkan sehingga CPU dapat memahami jenis instruksi apa itu. Ada banyak jenis, termasuk instruksi aritmatika, instruksi cabang, dan instruksi memori. Setelah CPU mengetahui jenis instruksi yang dijalankan, operan untuk instruksi tersebut diambil dari memori atau register CPU internal. Jika Anda ingin menambahkan angka A dan angka B, Anda tidak dapat menambahkan sampai Anda mengetahui nilai-nilai A dan B. Kebanyakan prosesor modern adalah 64-bit, yaitu, ukuran setiap nilai data adalah 64 bit.


64 bit adalah lebar register prosesor, saluran data dan / atau alamat memori. Untuk pengguna biasa, ini berarti berapa banyak informasi yang dapat diproses komputer pada satu waktu, dan ini paling baik dipahami dibandingkan dengan kerabat arsitektur yang lebih muda - prosesor 32-bit. Arsitektur 64-bit dapat memproses bit informasi dua kali lebih banyak pada satu waktu (64 bit versus 32).

Setelah menerima operan untuk instruksi, prosesor mentransfernya ke tahap eksekusi, di mana operasi dilakukan pada data yang masuk. Ini dapat menambahkan angka, melakukan manipulasi logis dengan angka, atau hanya melewati angka tanpa mengubahnya. Setelah menghitung hasilnya, akses memori mungkin diperlukan untuk menyimpannya, atau prosesor dapat menyimpan nilai di salah satu register internalnya. Setelah menyimpan hasilnya, CPU memperbarui keadaan berbagai elemen dan melanjutkan ke instruksi selanjutnya.

Penjelasan ini, tentu saja, sangat disederhanakan, dan sebagian besar prosesor modern membagi beberapa tahap ini menjadi 20 atau bahkan lebih kecil untuk meningkatkan efisiensi. Ini berarti bahwa meskipun prosesor dimulai dan diakhiri dengan beberapa instruksi dalam setiap siklus, mungkin diperlukan 20 siklus atau lebih untuk menjalankan satu instruksi dari awal hingga selesai. Model seperti itu biasanya disebut pipeline ("pipeline", biasanya diterjemahkan ke dalam bahasa Rusia sebagai "conveyor"), karena butuh waktu untuk mengisi pipeline dengan cairan dan menyelesaikannya, tetapi setelah mengisi aliran (output data) akan konstan.


Contoh konveyor 4 tahap. Persegi panjang multi-warna menunjukkan instruksi yang tidak tergantung satu sama lain.

Seluruh siklus yang dilalui instruksi adalah proses yang terkoordinasi dengan sangat hati-hati, tetapi tidak semua instruksi dapat diselesaikan pada saat yang sama. Misalnya, penambahan sangat cepat, dan membagi atau memuat dari memori dapat memakan waktu ribuan siklus. Alih-alih menghentikan seluruh prosesor hingga selesainya satu instruksi lambat, kebanyakan prosesor modern mengeksekusinya dengan perubahan urutan. Artinya, mereka menentukan instruksi mana yang paling menguntungkan untuk dieksekusi saat ini dan buffer instruksi lain yang belum siap. Jika instruksi saat ini belum siap, maka prosesor dapat melompat maju dalam kode untuk melihat apakah ada hal lain yang siap.

Selain mengeksekusi dengan urutan perubahan, prosesor modern menggunakan teknologi yang disebut arsitektur superscalar . Ini berarti bahwa setiap saat, prosesor secara bersamaan menjalankan banyak instruksi pada setiap tahap pipa. Dia juga dapat mengharapkan ratusan lebih untuk memulai eksekusi mereka, dan untuk dapat mengeksekusi beberapa instruksi secara bersamaan di dalam prosesor, ada beberapa salinan dari setiap tahap pipa. Jika prosesor melihat bahwa dua instruksi siap untuk dieksekusi, dan tidak ada ketergantungan di antara mereka, maka itu tidak menunggu sampai mereka selesai secara terpisah, tetapi menjalankannya secara bersamaan. Salah satu implementasi populer dari arsitektur ini disebut Simultaneous Multithreading (SMT) dan juga dikenal sebagai Hyper-Threading. Prosesor Intel dan AMD sekarang mendukung SMT dua sisi, sementara IBM telah mengembangkan chip yang mendukung hingga delapan SMT.


Untuk menyelesaikan eksekusi yang terkoordinasi dengan hati-hati ini, prosesor, selain inti dasar, memiliki banyak elemen tambahan. Prosesor memiliki ratusan modul terpisah, masing-masing memiliki fungsi tertentu, tetapi kami hanya akan mempertimbangkan dasar-dasarnya. Yang paling penting dan menguntungkan adalah cache dan prediktor transisi. Ada struktur tambahan lain yang tidak akan kami pertimbangkan: menata ulang buffer, mendaftar tabel penamaan ulang, dan stasiun cadangan.

Kebutuhan akan cache terkadang membingungkan, karena menyimpan data, seperti RAM atau SSD. Tetapi cache berbeda dalam latensi dan kecepatan akses. Meskipun memori RAM sangat cepat, ini adalah urutan besarnya lebih lambat dari yang dibutuhkan CPU. Ratusan siklus mungkin diperlukan untuk merespons dengan transfer data RAM, dan prosesor tidak akan melakukan apa-apa saat ini. Dan jika tidak ada data dalam RAM, maka mungkin dibutuhkan puluhan ribu siklus untuk mendapatkan akses ke mereka dari SSD. Tanpa cache, prosesor akan selalu berhenti.

Prosesor biasanya memiliki tiga level cache yang membentuk hirarki memori yang disebut. L1 cache adalah yang terkecil dan tercepat, L2 ada di tengah, dan L3 adalah yang terbesar dan paling lambat dari semua cache. Di atas cache dalam hierarki adalah register kecil yang menyimpan nilai data hanya selama perhitungan. Dalam urutan besarnya, register ini adalah perangkat penyimpanan tercepat dalam sistem. Ketika kompiler mengubah program tingkat tinggi menjadi bahasa rakitan, ia menentukan cara terbaik untuk menggunakan register ini.

Ketika CPU meminta data dari memori, pertama-tama ia memeriksa apakah data ini sudah disimpan dalam cache L1. Jika demikian, maka Anda dapat mengaksesnya hanya dalam beberapa siklus. Jika tidak ada, maka prosesor memeriksa L2, dan kemudian L3 cache. Cache diimplementasikan sedemikian rupa sehingga secara umum transparan ke kernel. Kernel hanya meminta data pada alamat memori yang ditentukan, dan level dalam hierarki di mana ia menjawabnya. Ketika pindah ke level berikutnya dalam hirarki memori, ukuran dan penundaan biasanya meningkat berdasarkan urutan besarnya. Pada akhirnya, jika CPU tidak menemukan data di salah satu cache, maka ia akan mengakses memori utama (RAM).


Dalam prosesor biasa, setiap inti memiliki dua cache L1: satu untuk data dan satu untuk instruksi. L1 cache biasanya memiliki kapasitas total sekitar 100 kilobyte dan ukurannya sangat bervariasi tergantung pada chip dan generasi prosesor. Selain itu, biasanya setiap inti memiliki cache L2 sendiri, meskipun dalam beberapa arsitektur mungkin sama untuk dua core. L2 cache biasanya berukuran beberapa ratus kilobyte. Akhirnya, ada cache L3 tunggal yang umum untuk semua core, dengan ukuran urutan puluhan megabyte.

Ketika prosesor mengeksekusi kode, instruksi dan nilai data yang paling sering digunakan di-cache. Ini secara signifikan mempercepat eksekusi, karena prosesor tidak perlu terus-menerus pergi ke memori utama untuk data yang diperlukan. Pada bagian kedua dan ketiga dari seri ini, kita akan berbicara lebih banyak tentang bagaimana sistem memori ini diimplementasikan.

Selain cache, salah satu blok bangunan terpenting dari prosesor modern adalah prediktor transisi yang akurat. Instruksi transisi (pencabangan) mirip dengan konstruksi if untuk prosesor. Satu set instruksi dijalankan jika kondisinya benar, dan yang lainnya jika salah. Sebagai contoh, kita perlu membandingkan dua angka, dan jika keduanya sama, lakukan satu fungsi, dan jika tidak sama, maka lakukan yang lain. Instruksi cabang ini sangat umum dan dapat membentuk sekitar 20% dari semua instruksi dalam suatu program.

Pada pandangan pertama, tampaknya instruksi percabangan ini seharusnya tidak menyebabkan masalah, tetapi eksekusi yang tepat bisa sangat menyulitkan prosesor. Pada waktu tertentu, prosesor mungkin sedang dalam proses mengeksekusi sepuluh atau dua puluh instruksi secara bersamaan, sehingga sangat penting untuk mengetahui instruksi mana yang harus dijalankan. Mungkin diperlukan 5 siklus untuk menentukan bahwa instruksi saat ini adalah transisi, dan 10 siklus lainnya untuk menentukan apakah kondisinya benar. Pada saat ini, prosesor sudah dapat mulai menjalankan puluhan instruksi tambahan, bahkan tanpa mengetahui apakah instruksi ini benar-benar cocok untuk dieksekusi.

Untuk mengatasi masalah ini, semua prosesor berkinerja tinggi modern menggunakan teknik yang disebut spekulasi. Ini berarti bahwa prosesor melacak instruksi cabang dan bertanya-tanya apakah cabang bersyarat akan dieksekusi atau tidak. Jika prediksi benar, maka prosesor sudah mulai menjalankan instruksi berikut, dan ini memberikan peningkatan kinerja. Jika prediksi salah, maka prosesor menghentikan eksekusi, menghapus semua instruksi salah yang mulai dijalankan, dan mulai lagi dari titik yang benar.

Prediktor cabang seperti itu adalah beberapa jenis pembelajaran mesin paling sederhana karena prediktor mempelajari perilaku cabang selama eksekusi. Jika dia terlalu sering salah memprediksi, dia mulai belajar perilaku yang benar. Penelitian selama beberapa dekade dalam teknik prediksi transisi telah menghasilkan akurasi prediksi lebih dari 90% pada prosesor modern.

Meskipun antisipasi memberikan peningkatan besar dalam kinerja, karena prosesor dapat menjalankan instruksi yang sudah siap, alih-alih menunggu dalam antrian eksekusi untuk dieksekusi, itu juga menciptakan kerentanan keamanan. Serangan Spectre yang terkenal mengeksploitasi bug dalam memprediksi dan mengantisipasi transisi. Penyerang menggunakan kode yang dipilih khusus untuk memaksa prosesor untuk secara proaktif mengeksekusi kode, yang menghasilkan kebocoran nilai dari memori. Untuk mencegah kebocoran data, perlu dilakukan desain ulang beberapa aspek antisipasi, yang menyebabkan sedikit penurunan kinerja.

Selama beberapa dekade terakhir, arsitektur yang digunakan dalam prosesor modern telah berkembang jauh. Inovasi dan pengembangan struktur yang dipikirkan dengan matang telah menyebabkan peningkatan produktivitas dan penggunaan perangkat keras yang lebih optimal. Namun, pengembang prosesor pusat dengan hati-hati menyimpan rahasia teknologi mereka, sehingga kami tidak dapat mengetahui apa yang sebenarnya terjadi di dalamnya. Namun, prinsip dasar prosesor adalah standar untuk semua arsitektur dan model. Intel dapat menambahkan bahan rahasianya untuk meningkatkan pangsa hit cache, dan AMD dapat menambahkan prediktor transisi yang ditingkatkan, tetapi prosesor dari kedua perusahaan melakukan tugas yang sama.

Dalam tampilan dan ulasan pertama ini, kami membahas dasar-dasar cara kerja prosesor. Pada bagian selanjutnya, kami akan memberi tahu Anda cara mengembangkan komponen yang membentuk prosesor, berbicara tentang elemen logika, frekuensi clock, manajemen daya, sirkuit, dan banyak lagi.

Bacaan yang Disarankan

Source: https://habr.com/ru/post/id456922/


All Articles