Saya menggunakan variasi filter median 5-silang pada data gambar pada sistem tertanam kecil, yaitu
x
x x x
x
Algoritma ini sangat sederhana: baca 5 nilai integer tanpa tanda, dapatkan 2 tertinggi, lakukan beberapa perhitungan pada nilai tersebut dan tulis kembali hasil integer tanpa tanda.
Yang menyenangkan adalah bahwa nilai input 5 integer semuanya berada dalam kisaran 0-20. Nilai bilangan bulat yang dihitung juga berada dalam kisaran 0-20!
Melalui profiling, saya telah menemukan bahwa mendapatkan dua angka terbesar adalah hambatan sehingga saya ingin mempercepat bagian ini. Apa cara tercepat untuk melakukan seleksi ini?
Algoritma saat ini menggunakan topeng 32 bit dengan 1 di posisi yang diberikan oleh 5 angka dan fungsi CLZ yang didukung HW.
Saya harus mengatakan bahwa CPU itu adalah milik perusahaan, tidak tersedia di luar perusahaan saya. Kompiler saya adalah GCC tetapi dibuat khusus untuk CPU ini.
Saya telah mencoba mencari tahu apakah saya bisa menggunakan tabel pencarian tetapi saya gagal menghasilkan kunci yang bisa saya gunakan.
Saya memiliki kombinasi untuk input tetapi pesanan tidak penting, yaitu sama dengan .[5,0,0,0,5]
[5,5,0,0,0]
Kebetulan fungsi hash di bawah ini menghasilkan hash sempurna tanpa tabrakan!
def hash(x):
h = 0
for i in x:
h = 33*h+i
return h
Tapi hash sangat besar dan tidak ada cukup memori untuk menggunakannya.
Apakah ada algoritma yang lebih baik yang bisa saya gunakan? Apakah mungkin untuk menyelesaikan masalah saya menggunakan tabel pencarian dan menghasilkan kunci?
sumber
hash
sudah melakukan lebih banyak operasi. Apakah panggilan selanjutnya ke metode terkait, misalnya apakah pusatx
bergerak melalui matriks baris-demi-baris?Jawaban:
Dalam jawaban saya yang lain saya menyarankan bahwa lompatan bersyarat mungkin menjadi hambatan utama untuk efisiensi. Sebagai akibatnya, jaringan penyortiran muncul dalam pikiran: mereka adalah data agnostik, yaitu urutan perbandingan yang sama dijalankan tidak peduli input, dengan hanya swap yang bersyarat.
Tentu saja, menyortir mungkin terlalu banyak pekerjaan; kita hanya membutuhkan dua angka terbesar. Beruntung bagi kami, jaringan seleksi juga telah dipelajari. Knuth memberi tahu kita bahwa menemukan dua angka terkecil dari lima² dapat dilakukan dengan perbandingan [1, 5.3.4 ex 19] (dan paling banyak sebanyak swap).U^2( 5 ) = 6
Jaringan yang ia berikan dalam solusi (ditulis ulang ke array berbasis nol) adalah
yang mengimplementasikan - setelah menyesuaikan arah perbandingan - dalam pseudocode sebagai
Sekarang, implementasi naif masih memiliki lompatan bersyarat (melintasi kode swap). Tergantung pada mesin Anda, Anda dapat menghubungi mereka dengan instruksi bersyarat. x86 tampaknya seperti lumpur biasa; ARM terlihat lebih menjanjikan karena sebagian besar operasi tampaknya tergantung pada dirinya sendiri. Jika saya memahami instruksi dengan benar, swap pertama diterjemahkan menjadi ini, dengan asumsi nilai array kami telah dimuat ke register
R0
melaluiR4
:Ya, ya, tentu saja Anda dapat menggunakan XOR swapping dengan EOR .
Saya hanya berharap prosesor Anda memiliki ini, atau yang serupa. Tentu saja, jika Anda membangunnya untuk tujuan ini, mungkin Anda bisa mendapatkan jaringan terprogram di sana?
Ini mungkin (terbukti?) Yang terbaik yang dapat Anda lakukan di dunia klasik, yaitu tanpa menggunakan domain terbatas dan melakukan sulap kata-kata jahat.
sumber
Hanya saja itu ada di atas meja, inilah algoritma langsung:
Dengan implementasi cerdas
if ... else
, seseorang dapat menyingkirkan beberapa lompatan tanpa syarat yang dimiliki terjemahan langsung.Ini jelek tapi hanya butuh
Faktanya, enam perbandingan optimal untuk masalah ini seperti yang ditunjukkan Teorema S di bagian 5.3.3 dari [1]; di sini kita membutuhkan .W2(5)
Ini tidak bisa diharapkan untuk cepat pada mesin dengan pipelining, meskipun; mengingat persentase tinggi dari lompatan bersyarat, sebagian besar waktu mungkin akan dihabiskan di warung.
Perhatikan bahwa varian yang lebih sederhana - urutkan
x1
danx2
, kemudian masukkan nilai-nilai lain selanjutnya - membutuhkan empat hingga tujuh perbandingan dan hanya lima hingga enam penugasan. Karena saya berharap lompatan lebih mahal di sini, saya terjebak dengan yang ini.sumber
Ini bisa menjadi aplikasi dan uji kasus yang bagus untuk proyek Souper . Souper adalah superoptimizer - alat yang mengambil urutan kode pendek sebagai input, dan mencoba mengoptimalkannya sebanyak mungkin (mencoba menemukan urutan kode yang setara yang akan lebih cepat).
Souper adalah open source. Anda mungkin mencoba menjalankan Souper pada cuplikan kode Anda untuk melihat apakah itu bisa lebih baik.
Lihat juga kontes John Regehr tentang penulisan kode cepat untuk mengurutkan 16 nilai 4-bit ; mungkin beberapa teknik di sana mungkin bermanfaat.
sumber
T[T[T[441*a+21*b+c]*21+d]*21+e]
sumber