Pertimbangkan program komputer yang sangat sederhana berikut ini:
for i = 1 to n:
y[i] = x[p[i]]
Di sini dan adalah elemen array byte, dan adalah array elemen kata. Di sini berukuran besar, misalnya, (sehingga hanya sebagian kecil dari data yang cocok dengan segala jenis memori cache).
Asumsikan bahwa terdiri dari angka acak , terdistribusi secara seragam antara dan .1 n
Dari perspektif perangkat keras modern, ini harus berarti sebagai berikut:
- membaca murah (membaca berurutan)
- membaca sangat mahal (bacaan acak; hampir semua bacaan adalah kesalahan cache; kita harus mengambil setiap byte individual dari memori utama)
- menulis murah (menulis berurutan).
Dan ini memang yang saya amati. Program ini sangat lambat dibandingkan dengan program yang hanya membaca dan menulis berurutan. Bagus.
Sekarang muncul pertanyaan: seberapa baik program ini berparalel pada platform multi-core modern?
Hipotesis saya adalah bahwa program ini tidak sejajar dengan baik. Bagaimanapun, bottleneck adalah memori utama. Satu core sudah menghabiskan sebagian besar waktunya hanya menunggu beberapa data dari memori utama.
Namun, ini bukan yang saya amati ketika saya mulai bereksperimen dengan beberapa algoritma di mana hambatannya adalah operasi semacam ini!
Saya hanya mengganti naif untuk-loop dengan paralel OpenMP untuk-loop (pada dasarnya, itu hanya akan membagi kisaran ke bagian yang lebih kecil dan menjalankan bagian-bagian ini pada core CPU yang berbeda secara paralel).
Pada komputer low-end, speedup memang kecil. Tetapi pada platform yang lebih tinggi saya terkejut bahwa saya mendapatkan speedup dekat-linear yang sangat baik. Beberapa contoh konkret (ketepatan waktu mungkin sedikit tidak tepat, ada banyak variasi acak; ini hanya eksperimen cepat):
2 x 4-core Xeon (total 8 core): faktor 5-8 percepatan dibandingkan dengan versi single-threaded.
2 x 6-core Xeon (total 12 core): faktor 8-14 percepatan dibandingkan dengan versi single-threaded.
Sekarang ini sama sekali tidak terduga. Pertanyaan:
Justru mengapa program semacam ini berparalel dengan sangat baik ? Apa yang terjadi pada perangkat keras? (Dugaan saya saat ini adalah sesuatu di sepanjang baris ini: pembacaan acak dari utas berbeda adalah "pipelined" dan tingkat rata-rata untuk mendapatkan jawaban untuk ini jauh lebih tinggi daripada dalam hal satu utas.)
Apakah perlu menggunakan beberapa utas dan beberapa inti untuk mendapatkan speedup? Jika semacam pipelining memang terjadi di antarmuka antara memori utama dan CPU, tidak bisakah aplikasi berulir tunggal membiarkan memori utama tahu bahwa itu akan segera membutuhkan , x [ p [ i + 1 ] ] , ... dan komputer bisa mulai mengambil garis cache yang relevan dari memori utama? Jika ini mungkin pada prinsipnya, bagaimana cara mencapainya dalam praktik?
Apa hak model teoritis yang bisa kita gunakan untuk menganalisis jenis program (dan membuat yang benar prediksi kinerja)?
Sunting: Sekarang ada beberapa kode sumber dan hasil benchmark tersedia di sini: https://github.com/suomela/parallel-random-read
Beberapa contoh angka rata-rata ( ):
- sekitar 42 ns per iterasi (baca acak) dengan utas tunggal
- sekitar 5 ns per iterasi (baca acak) dengan 12 core.