Tugasnya sederhana: menulis perakitan yang menghitung urutan besarnya bilangan bulat menggunakan sesedikit mungkin siklus clock.
- Urutan besarnya didefinisikan sebagai
log10
, bukanlog2
. - Kisaran input yang valid adalah
0
hingga , inklusif. Perilaku untuk input di luar rentang itu tidak ditentukan.1012
- Nilai harus dibulatkan ke bilangan bulat terdekat, dengan pengecualian bahwa input yang diberikan
0
output harus0
. (Anda dapat menganggap ini sebagai representasi terbaik dari infinity negatif yang dimungkinkan pada bilangan bulat tak bertanda). - Harus berupa perakitan x86.
- Integer harus berupa nilai runtime , bukan integer statis / inline. Jadi kita tidak tahu apa itu pada waktu kompilasi.
- Asumsikan bahwa Anda sudah memiliki bilangan bulat yang dimuat ke dalam register. (Tetapi sertakan pengaturan nilai dalam register dalam jawaban untuk kejelasan).
- Tidak dapat memanggil perpustakaan atau fungsi eksternal apa pun.
- Bebas menggunakan salah satu instruksi yang tersedia dalam dokumen Intel .
- Tidak ada C.
- Salah satu dari ~ 7 arsitektur Intel Core dapat diterima (dicantumkan pada halaman 10 ). Idealnya Nehalem (Intel Core i7).
Jawaban yang menang adalah yang menggunakan siklus jam sesedikit mungkin. Artinya, ia dapat memiliki operasi paling banyak per detik. Ringkasan perkiraan siklus jam ada di sini: http://www.agner.org/optimize/instruction_tables.pdf . Menghitung siklus jam dapat terjadi setelah jawaban diposting.
math
fastest-algorithm
assembly
Lance Pollard
sumber
sumber
Jawaban:
7 siklus, waktu konstan
Inilah solusi berdasarkan jawaban saya untuk Pertanyaan SO ini . Menggunakan BSR untuk menghitung berapa banyak bit yang diperlukan untuk memegang nomor tersebut. Itu terlihat berapa banyak angka desimal yang diperlukan untuk mewakili jumlah terbesar yang dapat menampung banyak bit. Maka mengurangi 1 jika angka aktual kurang dari kekuatan terdekat 10 dengan angka yang banyak.
Kompilasi pada GCC 4.6.3 untuk ubuntu dan mengembalikan nilai dalam kode keluar.
Saya tidak percaya diri menafsirkan tabel siklus untuk prosesor modern mana pun, tetapi menggunakan metode @ DigitalTrauma, pada prosesor Nehalim, saya mendapatkan 7 ?
sumber
The integer must be a runtime value, not a static/inline integer. So we don't know what it is at compile time.
Kasus terbaik 8 siklus, Kasus terburuk 12 siklus
Karena tidak jelas dalam pertanyaan, saya mendasarkan latensi Ivy Bridge ini.
Pendekatan di sini adalah dengan menggunakan
bsr
instruksi (bit scan reverse) sebagai log2 orang miskin (). Hasilnya digunakan sebagai indeks ke dalam tabel lompatan yang berisi entri untuk bit 0 hingga 42. Saya berasumsi bahwa mengingat operasi pada data 64bit secara implisit diperlukan, maka penggunaanbsr
instruksi adalah OK.Dalam input kasus terbaik, entri jumptable dapat memetakan
bsr
hasilnya langsung ke besarnya. mis. Untuk input dalam kisaran 32-63,bsr
hasilnya adalah 5, yang dipetakan dengan besaran 1. Dalam hal ini, jalur instruksi adalah:Dalam input kasus terburuk,
bsr
hasilnya akan memetakan ke dua besaran yang mungkin, sehingga entri jumptable melakukan satu tambahancmp
untuk memeriksa apakah inputnya> 10 n . Misalnya untuk input dalam kisaran 64-127,bsr
hasilnya akan menjadi 6. Entri jumptable yang sesuai kemudian memeriksa apakah input> 100 dan mengatur besarnya output yang sesuai.Selain untuk jalur kasus terburuk, kami memiliki instruksi mov tambahan untuk memuat nilai langsung 64bit untuk digunakan di
cmp
, jadi jalur instruksi kasus terburuk adalah:Ini kodenya:
Ini sebagian besar dihasilkan dari output assembler gcc untuk kode C proof-of-concept yang saya tulis . Perhatikan kode C menggunakan goto yang dapat dihitung untuk mengimplementasikan tabel lompatan. Ia juga menggunakan
__builtin_clzll()
gcc builtin, yang mengkompilasibsr
instruksi (plus anxor
).Saya mempertimbangkan beberapa solusi sebelum sampai pada yang ini:
FYL2X
untuk menghitung log natural, makaFMUL
dengan konstanta yang diperlukan. Ini mungkin akan memenangkan ini jika ini adalah kontes [tag: instructions: golf]. TetapiFYL2X
memiliki latency 90-106 untuk jembatan Ivy.Pencarian biner dengan kode keras. Ini mungkin sebenarnya kompetitif - saya akan menyerahkannya kepada orang lain untuk diimplementasikan :).
Tabel hasil pencarian lengkap. Ini saya yakin secara teoritis tercepat, tetapi akan membutuhkan tabel pencarian 1TB - belum praktis - mungkin dalam beberapa tahun jika Hukum Moore terus berlaku.
sumber
jmp
danjcc
tidak memiliki latensi, hanya biaya throughput. Prediksi cabang + eksekusi spekulatif berarti dependensi kontrol bukan bagian dari rantai ketergantungan data.