Menggunakan banyak core membutuhkan secara eksplisit mengekspos paralelisme level-thread ke OS, yang biasanya mengharuskan programmer untuk menulis program multi-threaded. (Atau untuk menjalankan program single-threaded beberapa kali pada input yang berbeda, seperti kompilasi dengan make -j4
)
Kompiler untuk beberapa bahasa mendukung paralelisasi otomatis. Sebagai contoh, C atau C ++ dengan OpenMP dapat mengkompilasi for()
loop biasa ke dalam program yang memulai banyak utas.
#pragma omp parallel for
for(int i = 0; i < 1000000; ++i)
{
A[i] = B[i] * constant + C[i];
}
Tapi tetap saja, ini harus terjadi ketika Anda menulis atau menyusun program. Tidak ada cara untuk perangkat keras dan OS saat ini untuk menggunakan banyak core untuk mempercepat program single-threaded.
Terkait: Bagaimana cara menjalankan satu utas pada beberapa inti? : jawaban: mereka tidak. Tetapi ada jenis paralelisme lain, seperti paralelisme tingkat Instruksi yang ditemukan dan dieksploitasi oleh inti CPU tunggal untuk menjalankan utas tunggal lebih cepat dari satu instruksi pada satu waktu.
Jawaban saya atas pertanyaan itu masuk ke beberapa perincian tentang bagaimana CPU modern menemukan dan mengeksploitasi paralelisme tingkat instruksi yang berbutir halus. (Sebagian besar berfokus pada x86). Itu hanya bagian dari cara kerja CPU normal, dengan memiliki beberapa instruksi dalam satu penerbangan sekaligus, dan bukan sesuatu yang perlu Anda aktifkan secara khusus. (Ada penghitung kinerja yang dapat memungkinkan Anda melihat berapa banyak instruksi per jam yang berhasil dijalankan CPU Anda saat menjalankan program, atau tindakan lainnya.)
Perhatikan bahwa RPi3 menggunakan inti CPU ARM Cortex-A53 yang dipesan . Setiap inti adalah superscalar 2-lebar (2 instruksi per jam sebagaimana diizinkan ILP), tetapi tidak dapat menyusun ulang instruksi untuk menemukan lebih banyak paralelisme tingkat instruksi dan menyembunyikan latensi.
Namun, CPU masih dalam tahap pipeline, sehingga jumlah total instruksi dalam penerbangan (mulai dari mengambil dan mendekode hingga ke tahap penulisan kembali pada akhir pipa) sangat signifikan. Ketika dependensi data tidak membatasi hal-hal, mungkin ada 2 instruksi di setiap tahap pipa yang sedang dikerjakan CPU, dengan throughput 2 instruksi per jam. (Itulah artinya 2-lebar.)
Itu tidak dapat menjalankan instruksi yang rusak, tetapi dengan pemesanan instruksi yang hati-hati (biasanya oleh kompiler) ia masih dapat menyembunyikan latensi dari suatu instruksi yang membutuhkan banyak siklus agar hasilnya siap. (mis. memuat bahkan jika hit di cache atau multiply akan membutuhkan banyak siklus, vs. penambahan yang siap pada siklus berikutnya). Caranya adalah dengan memesan instruksi asm sehingga ada beberapa instruksi independen antara yang menghasilkan hasil dan yang menggunakannya.
Memiliki perangkat lunak (kompiler) menjadwalkan instruksi secara statis lebih rapuh daripada memiliki perangkat keras yang dapat memesan ulang secara internal sambil mempertahankan ilusi berjalan dalam urutan program. Sangat sulit bagi kompiler untuk melakukan pekerjaan sebaik bahkan jendela kecil yang tidak sesuai pesanan untuk menyusun ulang instruksi karena cache-misses tidak dapat diprediksi, dan sulit untuk menganalisis rantai ketergantungan di seluruh panggilan fungsi pada waktu kompilasi. Dan jumlah register terbatas tanpa penggantian nama perangkat keras.
Semua ini adalah kenyamanan kecil ketika kode Anda berjalan lebih lambat dari yang Anda inginkan. Tentu ada banyak hal keren di bawah tenda di Cortex-A53, tapi ada lebih banyak barang keren di bawah tenda di Cortex-A57 (seperti eksekusi out-of-order hingga 3 instruksi per jam), dan lebih banyak lagi di CPU x86 besar seperti Skylake (belum lagi perbedaan kecepatan clock).
Cortex-A53 cukup fantastis dibandingkan dengan https://en.wikipedia.org/wiki/Classic_RISC_pipeline seperti MIPS asli yang akan Anda pelajari di kelas arsitektur komputer, tetapi menurut standar modern itu cukup rendah.