Saya ingin membangun bitmap selama runtime. Bitmap harus scalable di semua sisi dan akses pixel harus cukup efisien.
Beberapa ilustrasi http://img546.imageshack.us/img546/4995/maptm.jpg
Antara dan setelah perintah yang ditunjukkan pada gambar, Map.setPixel () dan Map.getPixel () harus mengatur / mengembalikan data yang disimpan dalam bitmap.
Saya tidak mengharapkan implementasi hanya konsep bagaimana mengalokasikan memori sedemikian rupa sehingga setPixel () / getPixel secepat mungkin.
extendX
metode untuk membuatsetPixel
dangetPixel
yang cepat?Jawaban:
Jika
extend()
operasi perlu cukup cepat, Quadtree mungkin cocok; sebenarnya bahkan tidak memerlukan operasi perluasan yang eksplisit. Memang, itu tidak akan menghasilkan kinerja yang optimal untuk akses acak ke piksel individu, tetapi komentar Anda mengatakan bahwa operasi utama Anda adalah iterasi dari piksel, yang quadtree bisa lakukan sangat cepat, mungkin hampir secepat implementasi berbasis matriks (dan lebih cepat jika iterasi tidak selalu terjadi dengan cara yang sama, matriks diletakkan).Persyaratan Anda sebenarnya terdengar seperti Anda mencoba menerapkan otomat seluler seperti Game of Life. Anda mungkin ingin melihat Hashlife , cara yang sangat berkinerja tinggi untuk mengimplementasikan Game of Life di grid yang tak terbatas. Perhatikan bahwa ini didasarkan pada Quadtree, tetapi melakukan beberapa optimasi tambahan yang sangat cerdas berdasarkan lokalitas aturan permainan.
sumber
@SecStone mengatakan bahwa ada cukup waktu untuk operasi ekspansi, jadi cara termudah dan paling efisien untuk menyimpan piksel adalah dengan menggunakan susunan datar tunggal atau susunan dua dimensi, karena piksel dapat diakses dalam waktu yang konstan.
sumber
Dengan tangan
Jika memori bukan sumber daya yang sangat jarang, saya menganggap bekerja di potongan yang lebih besar.
Berikut ini beberapa kode semu.
Implementasi ini cukup naif.
Untuk satu, itu menciptakan potongan di getPixel (pada dasarnya itu akan baik-baik saja untuk mengembalikan 0 atau lebih, jika tidak ada potongan didefinisikan untuk posisi itu). Kedua didasarkan pada asumsi, bahwa Anda memiliki implementasi Peta yang cukup cepat dan terukur. Setahu saya setiap bahasa yang baik memiliki satu.
Anda juga harus bermain dengan ukuran chunk. Untuk bitmap yang padat, ukuran chunk yang besar adalah baik, untuk bitmap yang jarang, ukuran chunk yang lebih kecil lebih baik. Bahkan untuk yang sangat jarang, "ukuran chunk" dari 1 adalah yang terbaik, menjadikan "chunk" itu sendiri usang dan mengurangi struktur data menjadi peta int dari peta piksel int.
Dari rak
Solusi lain mungkin dengan melihat beberapa perpustakaan grafis. Mereka sebenarnya cukup bagus dalam menggambar satu buffer 2D ke yang lain. Itu berarti Anda hanya akan mengalokasikan buffer yang lebih besar dan memiliki yang asli ditarik ke dalamnya di koordinat yang sesuai.
Sebagai strategi umum: Ketika memiliki "blok memori yang tumbuh secara dinamis", adalah ide yang baik untuk mengalokasikan beberapa dari itu, setelah digunakan. Ini agak menghabiskan banyak memori, tetapi secara signifikan memotong alokasi dan biaya penyalinan . Sebagian besar implementasi vektor mengalokasikan dua kali ukurannya, ketika terlampaui. Jadi terutama jika Anda menggunakan solusi yang tidak tersedia, jangan memperpanjang buffer Anda hanya dengan 1 pixel, karena hanya satu pixel yang diminta. Memori yang dialokasikan murah. Realokasi, menyalin, dan melepaskan itu mahal.
sumber
Hanya beberapa poin saran:
Jika Anda menerapkan ini sebagai array dari beberapa tipe integral (atau array array ...), Anda mungkin harus menumbuhkan array pendukung dengan sejumlah bit / piksel setiap kali untuk menghindari keharusan menggeser bit saat Anda menyalinnya. Sisi buruknya adalah Anda menggunakan lebih banyak ruang, tetapi proporsi ruang terbuang turun seiring bitmap semakin besar.
Jika Anda menggunakan struktur data berbasis Peta, Anda dapat memperbaiki masalah menumbuhkan bitmap hanya dengan memindahkan x, y mengoordinasikan argumen
getPixel
dansetPixel
panggilan.Jika Anda menggunakan struktur data berbasis Peta, Anda hanya perlu entri peta untuk "yang". "Nol" dapat ditunjukkan dengan tidak adanya entri. Ini menghemat banyak ruang, terutama jika bitmap sebagian besar nol.
Anda tidak perlu menggunakan Peta. Anda dapat menyandikan
int
pasangan x, y sebagai satulong
. Proses analog dapat digunakan untuk memetakan array array ke array.Akhirnya, Anda perlu menyeimbangkan 3 hal:
getPixel
dansetPixel
,extend*
operasi, dansumber
Sebelum mencoba hal lain yang lebih rumit, dan kecuali Anda tidak dapat menyimpan semuanya dalam memori, pertahankan segala sesuatunya sederhana dan gunakan array dua dimensi bersama dengan informasi tentang asal-usul sistem koordinat Anda. Untuk memperluasnya, gunakan strategi yang sama seperti, misalnya, vektor C ++ std ::: membuat perbedaan antara ukuran aktual array Anda dan kapasitas array, dan memperluas kapasitas dalam potongan setiap kali batas tercapai. "kapasitas" di sini harus didefinisikan dalam hal interval (from_x, to_x), (from_y, to_y).
Ini mungkin memerlukan realokasi memori yang lengkap dari waktu ke waktu, tetapi selama ini tidak terlalu sering terjadi, mungkin cukup cepat untuk tujuan Anda (sebenarnya, Anda harus mencoba / profil ini).
sumber
Cara tercepat mutlak untuk melakukan akses piksel adalah array dua dimensi dari piksel yang dapat dialamatkan secara individual.
Untuk ekstensi, mulailah dengan implementasi sederhana yang realokasi dan salin setiap waktu (karena Anda tetap membutuhkan kode itu). Jika profiling tidak menunjukkan bahwa Anda menghabiskan banyak waktu untuk itu, tidak perlu disempurnakan lagi.
Jika pembuatan profil menunjukkan kebutuhan untuk menjaga agar jumlah alokasi ulang tetap rendah dan Anda tidak dibatasi oleh memori, pertimbangkan untuk mengalokasikan terlalu banyak dengan persentase di setiap arah dan menyimpan offset ke titik asal. (Misalnya, jika Anda memulai bitmap baru pada 1x1 dan mengalokasikan array 9x9 untuk menahannya, yang awal
x
dany
offset akan menjadi4
.) Trade-off di sini adalah harus melakukan matematika tambahan selama akses piksel untuk menerapkan offset.Jika ekstensi ternyata sangat mahal, Anda dapat mencoba salah satu dari keduanya:
Menangani ekstensi vertikal dan horizontal secara berbeda. Memperluas array secara vertikal ke segala arah dapat dilakukan dengan mengalokasikan blok baru dan melakukan satu salinan dari seluruh array yang ada ke offset yang sesuai di memori baru. Bandingkan dengan ekstensi horisontal, di mana Anda harus melakukan operasi itu sekali per baris karena data yang ada tidak bersebelahan di blok baru.
Pantau jumlah dan arah ekstensi yang paling sering. Gunakan informasi itu untuk memilih ukuran dan offset baru yang akan mengurangi kemungkinan harus melakukan alokasi ulang dan salin untuk ekstensi apa pun.
Secara pribadi, saya ragu Anda akan membutuhkan keduanya kecuali rasio piksel-akses-terhadap-ekstensi rendah.
sumber
Map.setPixel()
danMap.getPixel()
yang memodifikasi satu piksel pada satu waktu, juga menyediakan metode yang menyalin dan mengubah satu persegi panjang piksel sekaligus. Ini akan memungkinkan pemanggil untuk memilih bentuk akses yang lebih efisien tergantung pada informasi yang tersedia untuk pemanggil.(Mari kita tidak menjawab jawaban lucu ...)
sumber
Implementasi yang paling fleksibel dan mungkin dapat diandalkan adalah daftar tertaut dengan struct yang memberikan nilai x-koordinat, koordinat y, dan bit. Saya akan membangun itu dulu dan membuatnya bekerja.
Kemudian, jika terlalu lambat dan / atau besar, coba cara-cara biasa untuk mempercepatnya: array, matriks, bitmap, kompresi, caching, inversi, menyimpan hanya nilai '1', dll.
Lebih mudah untuk membuat implementasi benar lambat lebih cepat daripada memperbaiki implementasi cepat kereta. Dan saat menguji implementasi kedua 'cepat' Anda, Anda memiliki standar referensi untuk membandingkannya.
Dan, siapa tahu, Anda mungkin akan menemukan bahwa versi lambatnya cukup cepat. Selama seluruh struktur pas di memori, semuanya sudah luar biasa cepat.
sumber
Saya mengusulkan implementasi berikut dengan Python:
Ini memiliki keuntungan sebagai berikut:
map[(1,2)]
dapat dipertimbangkanO(1)
.sumber
Jika Anda benar - benar membutuhkan bitmap dari ukuran sembarang - dan maksud saya apa pun mulai dari 1x1 hingga 1000000x1000000 amd ke atas, dan perlu diperluas sesuai permintaan ... salah satu cara yang mungkin adalah dengan menggunakan database. Pada awalnya mungkin terlihat kontra intuitif, tetapi yang Anda miliki sebenarnya adalah masalah penyimpanan. Basis data akan memungkinkan Anda mengakses setiap piksel dan menyimpan sejumlah data secara esensial. Saya tidak perlu berarti SQL db, btw.
Apakah akan cukup cepat untuk keperluan Anda? Saya tidak bisa menjawab, karena tidak ada konteks di sini mengenai apa yang Anda lakukan dengan bitmap ini. Tetapi jika ini untuk tampilan layar, pertimbangkan bahwa Anda umumnya hanya perlu menarik kembali baris pindai tambahan untuk ditampilkan saat layar bergulir, tidak semua data.
Yang sedang berkata, saya tidak bisa membantu tetapi bertanya-tanya apakah Anda akan melakukan sesuatu yang salah. Apakah sebaiknya Anda menggunakan grafis berbasis vektor dan melacak setiap individu dalam memori, dan kemudian membuat bitmap hanya sebesar yang diperlukan untuk layar?
sumber
Berikut langkah-langkah untuk membuatnya berfungsi dengan baik:
contoh implementasi adalah:
Jelas untuk implementasi nyata, XSize () dan YSize () tidak akan berfungsi, tetapi Anda akan membutuhkan MinX (), MaxX (), MinY (), MaxY () atau sesuatu seperti itu untuk menjaga angka indeks konsisten.
sumber