Saya mencoba untuk memparalelkan pelacak sinar. Ini berarti saya memiliki daftar penghitungan kecil yang sangat panjang. Program vanilla berjalan pada adegan tertentu dalam 67,98 detik dan penggunaan memori total 13 MB dan produktivitas 99,2%.
Dalam upaya pertama saya, saya menggunakan strategi paralel parBuffer
dengan ukuran buffer 50. Saya memilih parBuffer
karena ini berjalan melalui daftar hanya secepat bunga api dikonsumsi, dan tidak memaksa tulang belakang daftar seperti parList
, yang akan menggunakan banyak memori karena daftarnya sangat panjang. Dengan -N2
, itu berjalan dalam waktu 100,46 detik dan 14 MB penggunaan memori total dan produktivitas 97,8%. Informasi percikannya adalah:SPARKS: 480000 (476469 converted, 0 overflowed, 0 dud, 161 GC'd, 3370 fizzled)
Proporsi percikan api yang mendesis menunjukkan bahwa butiran bunga api terlalu kecil, jadi selanjutnya saya mencoba menggunakan strategi parListChunk
, yang membagi daftar menjadi beberapa bagian dan menciptakan percikan untuk setiap bagian. Saya mendapatkan hasil terbaik dengan ukuran sebagian 0.25 * imageWidth
. Program ini berjalan dalam 93,43 detik dan total penggunaan memori 236 MB dan produktivitas 97,3%. Informasi spark adalah: SPARKS: 2400 (2400 converted, 0 overflowed, 0 dud, 0 GC'd, 0 fizzled)
. Saya percaya penggunaan memori yang jauh lebih besar adalah karena parListChunk
memaksa tulang punggung daftar.
Kemudian saya mencoba menulis strategi saya sendiri yang dengan malas membagi daftar menjadi beberapa bagian dan kemudian meneruskan potongan tersebut parBuffer
dan menggabungkan hasilnya.
concat $ withStrategy (parBuffer 40 rdeepseq) (chunksOf 100 (map colorPixel pixels))
Ini berjalan dalam 95,99 detik dan 22MB dari total penggunaan memori dan produktivitas 98,8%. Ini berhasil dalam arti bahwa semua percikan api diubah dan penggunaan memori jauh lebih rendah, namun kecepatannya tidak ditingkatkan. Berikut adalah gambar bagian dari profil eventlog.
Seperti yang Anda lihat, utas dihentikan karena heap overflow. Saya mencoba menambahkan +RTS -M1G
yang meningkatkan ukuran heap default hingga 1Gb. Hasilnya tidak berubah. Saya membaca bahwa utas utama Haskell akan menggunakan memori dari heap jika tumpukannya meluap, jadi saya juga mencoba meningkatkan ukuran tumpukan default juga +RTS -M1G -K1G
tetapi ini juga tidak berdampak.
Apakah ada hal lain yang bisa saya coba? Saya dapat memposting info profil yang lebih rinci untuk penggunaan memori atau eventlog jika diperlukan, saya tidak memasukkan semuanya karena ini adalah informasi yang banyak dan saya tidak berpikir semua itu perlu disertakan.
EDIT: Saya membaca tentang dukungan multicore Haskell RTS , dan ini berbicara tentang adanya HEC (Haskell Execution Context) untuk setiap inti. Setiap HEC berisi, antara lain, Area Alokasi (yang merupakan bagian dari satu heap bersama). Setiap kali Area Alokasi HEC habis, pengumpulan sampah harus dilakukan. Tampaknya opsi RTS untuk mengontrolnya, -A. Saya mencoba -A32M tetapi tidak melihat perbedaan.
EDIT2: Ini adalah tautan ke repo github yang didedikasikan untuk pertanyaan ini . Saya telah menyertakan hasil pembuatan profil di folder profiling.
EDIT3: Ini sedikit kode yang relevan:
render :: [([(Float,Float)],[(Float,Float)])] -> World -> [Color]
render grids world = cs where
ps = [ (i,j) | j <- reverse [0..wImgHt world - 1] , i <- [0..wImgWd world - 1] ]
cs = map (colorPixel world) (zip ps grids)
--cs = withStrategy (parListChunk (round (wImgWd world)) rdeepseq) (map (colorPixel world) (zip ps grids))
--cs = withStrategy (parBuffer 16 rdeepseq) (map (colorPixel world) (zip ps grids))
--cs = concat $ withStrategy (parBuffer 40 rdeepseq) (chunksOf 100 (map (colorPixel world) (zip ps grids)))
Kisi adalah pelampung acak yang dihitung sebelumnya dan digunakan oleh colorPixel. Jenisnya colorPixel
adalah:
colorPixel :: World -> ((Float,Float),([(Float,Float)],[(Float,Float)])) -> Color
Strategy
. Seharusnya memilih kata yang lebih baik. Selain itu, masalah heap overflow terjadi dengan parListChunk
dan parBuffer
juga.
concat $ withStrategy …
? Saya tidak bisa mereproduksi perilaku ini6008010
, yang merupakan komitmen terdekat untuk hasil edit Anda.