Mengapa mesin perlu dioptimalkan untuk prosesor baru dengan arsitektur yang sama?


39

Ketika generasi prosesor baru dirilis, sebagian besar situs web melaporkan bahwa mesin dan program game perlu dioptimalkan untuk perangkat keras baru. Saya tidak begitu mengerti mengapa. Prosesor biasanya memiliki arsitektur yang mendefinisikan jenis instruksi yang digunakan. Yang kita semua gunakan saat ini adalah amd_x86_64. Mengapa setiap program atau kompiler perlu diperbarui jika semua prosesor menggunakan arsitektur yang sama? Tentunya ada fitur DALAM pipeline prosesor baru yang mengoptimalkan pelaksanaan kode mesin, tetapi mengapa kode mesin itu sendiri perlu diubah jika arsitektur tidak?


Komentar bukan untuk diskusi panjang; percakapan ini telah dipindahkan ke obrolan .
Josh

14
"Kebutuhan" adalah kata-kata yang salah, dan lebih banyak pemasaran daripada kebenaran, banyak dengan cara yang sama seperti misalnya Windows perlu mendukung generasi CPU baru tertentu (atau tidak, seperti dalam kasus Windows 7, yang pada prinsipnya akan bekerja dengan sempurna baik dengan misalnya Ryzen, kecuali untuk menggunakan daya 3-4% lebih dari yang diperlukan). Penyesuaian ini hanya tentang mencoba memeras sedikit lebih banyak dari CPU, semakin mendekati maksimum. Secara realistis, Anda mungkin dapat memperoleh 1-2% keseluruhan dalam contoh-contoh yang tidak dibuat-buat karena penjadwalan yang berbeda dan menggunakan beberapa instruksi baru.
Damon

2
Hanya karena dua prosesor dapat melakukan operasi yang sama, itu tidak berarti operasi memiliki kinerja yang sama pada kedua prosesor ...
Mehrdad

Lihat pertanyaan terkait saya di Stack Overflow: Bagaimana cara mtune bekerja?
Marc.2377

Jawaban:


54

Karena generasi berbeda dari arsitektur yang sama dapat memiliki set instruksi yang berbeda .

Sebagai contoh, Streaming SIMD Extensions mungkin adalah set instruksi x86 yang paling terkenal, namun, dan meskipun hanya ada satu arsitektur x86, terdapat SSE, SSE2, SSE3, dan SSE4.

Masing-masing generasi ini dapat menyertakan instruksi baru yang menyediakan cara lebih cepat untuk melakukan operasi tertentu. Contoh yang relevan dengan game mungkin adalah instruksi titik produk.

Jadi jika mesin game dikompilasi untuk generasi arsitektur sebelumnya, ia tidak akan memiliki dukungan untuk instruksi yang lebih baru ini. Demikian pula, mungkin perlu mengoptimalkan mesin untuk instruksi yang lebih baru; SSE4 , misalnya, memiliki dukungan untuk instruksi produk titik yang bekerja pada data array-of-struct. Optimalisasi yang dapat memanfaatkan instruksi baru ini adalah mengubah tata letak data Anda menjadi array-of-struct.


1
@ Panzercrisis - terima kasih atas saran edit. Agar lebih jelas: pertanyaan awal bukan tentang kode Anda sendiri, itu tentang kode mesin, jadi "optimalkan kode Anda sendiri" bukan saran edit yang baik. Namun, itu menyoroti bahwa saya perlu mengklarifikasi bahwa ketika saya berkata "optimalkan" saya maksudkan "optimalkan kode mesin", jadi saya telah mengedit untuk mengambilnya.
Maximus Minimus

37

Jawaban Maximus benar, saya hanya ingin memberikan cerita lain:

Perangkat keras itu sendiri berubah dengan cara Anda perlu mengubah cara Anda membuat kode, terlepas dari instruksi yang baru diperkenalkan.

  • Menambah atau mengurangi jumlah cache berarti Anda perlu khawatir kurang atau lebih tentang optimasi cache / ketidakabsahan cache yang menjadi masalah. Lebih banyak cache berarti dengan data kecil, Anda bisa lebih sedikit fokus untuk memastikan data bersebelahan dengan keluar ke masalah kinerja. Lebih sedikit cache berarti ini bisa menjadi masalah, dan sangat sedikit cache artinya dengan beberapa struktur data besar itu tidak masalah.

  • Level cache yang baru berarti Anda perlu memikirkan lebih lanjut tentang bagaimana Anda mengatur set data yang lebih besar (L1, vs L2, vs L3 vs L4).

  • Semakin banyak core berarti Anda perlu memikirkan bagaimana Anda akan menjalankan aplikasi multi-thread dengan lebih baik, dan bagaimana aplikasi Anda berkembang dalam lingkungan multi-proses.

  • Jam yang lebih cepat berarti Anda harus mulai memikirkan latensi memori lebih dari yang harus Anda pikirkan tentang kecepatan komputasi CPU sebagai penghambat sistem Anda.

  • Jumlah FPU pada suatu sistem mungkin tidak lagi sesuai dengan jumlah ALU integer per inti lagi (AMD memiliki / memiliki arsitektur seperti ini).

  • Jumlah siklus jam yang diperlukan untuk menghitung operasi saya telah menurun, atau meningkat.

  • Jumlah register yang tersedia berubah.

Semua ini memiliki dampak kinerja yang sangat nyata pada program yang membuat asumsi tentang arsitektur yang mendasari pada perangkat keras sebelumnya dengan ISA yang sama, baik positif atau negatif.


"Peningkatan atau penurunan level cache berarti Anda tidak perlu terlalu khawatir tentang koherensi cache." - hampir semua CPU adalah cache yang koheren. Apakah maksud Anda berbagi salah? Bahkan daripada hampir semua baris $ CPU hampir selalu 64 B ...
Maciej Piechotka

1
Maciej baru saja mengambil pernyataan Anda tentang koherensi cache :) Anda mungkin bermaksud "optimasi cache" atau sesuatu. Cache coherence adalah kemampuan suatu sistem untuk menjaga pandangan yang konsisten terhadap memori secara transparan ke perangkat lunak bahkan jika di hadapan N cache yang independen . Ini sepenuhnya ortogonal dengan ukurannya. TBH pernyataan itu tidak benar-benar relevan tetapi jawaban Anda (terutama poin 5 & 6) menjawab pertanyaan dengan lebih baik daripada yang diterima IMO :) Mungkin menekankan perbedaan antara arsitektur dan arsitektur-u akan membuatnya lebih menonjol.
Margaret Bloom

4
"Seperti penggandaan mengambil lebih banyak waktu daripada penambahan, di mana seperti hari ini di intel modern dan amd CPUS dibutuhkan jumlah waktu yang sama" Itu tidak semua benar. Dalam arsitektur pipelined Anda harus membedakan antara latensi (ketika hasilnya siap) dan throughput (berapa banyak yang dapat Anda lakukan per siklus). Tambahan Int pada prosesor Intel modern memiliki throughput 4 dan latensi 1. Multiply memiliki throughput 1 dan latensi 3 (atau 4). Ini adalah hal-hal yang berubah dengan setiap arsitektur dan perlu optimasi. Misalnya pdepmembutuhkan 1 siklus pada intel tetapi 6 pada Ryzen jadi mungkin tidak ingin menggunakannya pada Ryzen.
Christoph

2
@Clearer Saya tahu kita berbicara tentang CPU di sini, tetapi Anda belum pernah memprogram untuk GPU, bukan? Kode yang sama menghasilkan hasil yang sangat berbeda dalam kinerja yang sering kali Anda dipaksa untuk mempertimbangkan kemampuan perangkat keras di CUDA. Di situlah saya berasal dengan ini, ukuran cache (memori bersama, dikelola L1 cache) sebenarnya perlu dipertimbangkan dalam cara Anda kode sesuatu di CUDA.
whn

2
@Christoph benar. Benchmark yang Anda tautkan adalah untuk loop di atas array c[i] = a[i] OP b[i](yaitu 2 beban dan 1 toko per operasi) sehingga waktu didominasi oleh bandwidth memori karena intensitas komputasi yang sangat rendah. Ukuran array tidak ditampilkan jadi IDK jika cocok dengan L1D. ( gcc4.9 -Ofastsangat mungkin auto-vectorized loop tersebut, jadi Anda bahkan tidak mengukur biaya operasi skalar normal sebagai bagian dari kode integer kompleks). Baris pertama dari halaman itu adalah PENTING: Umpan balik yang bermanfaat mengungkapkan bahwa beberapa tindakan ini sangat cacat. Pembaruan besar sedang dalam perjalanan .
Peter Cordes

2

Bahkan di luar perubahan besar seperti dukungan untuk instruksi baru, produsen mikroprosesor secara konstan memodifikasi desain mereka untuk meningkatkan kinerja, dan setiap desain baru dapat memiliki kinerja relatif yang berbeda untuk setiap instruksi atau teknik. Mungkin Anda menulis beberapa kode branchless yang dioptimalkan dengan hati-hati untuk Model X, tetapi Model Y memiliki prediktor cabang yang ditingkatkan yang mengurangi hukuman kesalahan prediksi untuk versi kode non-branchless (yang juga membebaskan register untuk digunakan di tempat lain) . Mungkin Model Y mendukung paralelisme yang lebih besar dari instruksi latensi tinggi tertentu, sehingga sekarang loop yang tidak diawasi dari instruksi tersebut membuat Anda mendapatkan throughput yang lebih baik, sedangkan pada Model X urutan yang lebih pendek lebih baik.

Masalah apa pun dapat diselesaikan dengan banyak cara, dan setiap program merupakan kumpulan pengorbanan dan alokasi sumber daya yang saling terkait, dari sudut optimasi. Bahkan perubahan kecil dalam ketersediaan sumber daya tersebut atau biaya sepotong kode tertentu dalam hal sumber daya tersebut, dapat memiliki efek kaskade yang memberikan keuntungan kinerja yang substansial pada satu bagian kode atau lainnya. Bahkan jika sebuah chip yang ditingkatkan memiliki "lebih dari segalanya", berapa banyak lagi dari setiap hal dapat mengayunkan keseimbangan.

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.