[問題] 程式使用記憶體的上限
各位好,小弟用Qt Creator寫了一個瀏覽照片的程式
程式中會大量的開啟指定的圖檔然後顯示到視窗中
但每次讀取到一定的量後,程式就會沒辦法再讀取圖片
嚴重甚至崩潰,檢查後才發現似乎跟程式使用的記憶體有關
每當我程式讀取的圖片佔用的記憶體到了1.2G以上,
程式很容易就無法再讀取圖片了,
我很確定我電腦的記憶體還有很多尚未使用的部分@@
我電腦有16G的記憶體,作業系統是WIN7 64位元
我用工作管理員看效能那一欄下面的實體記憶體部分有四個內容
分別是『總共、快取的、可用、未使用』
根據我GOOGLE查到的結果,『未使用』其實只是還沒被作業系統移到『快取的』而已
電腦閒置的時間越久,未使用就會越少,快取的就會越多,
這樣電腦中的程式要用到記憶體時就可以迅速的從『快取的』取出來使用,
我打開電腦的VM ware時,『快取的』的確會大量的減少
但我發現我程式每次在讀取圖片時,『快取的』都不會減少,
反而減少的都是『未使用』
當下一張讀取的圖片檔案大小超過『未使用』時,程式就沒辦法讀取照片了@@
而剛好我電腦的『未使用』每次都差不多是剩1.1G左右
我不知道這段敘述跟我遇到的問題有沒有相關ˇ_ˇ
我也不敢100%確定我這段敘述真的是正確的
所以想請問該怎麼樣才可以讓程式讀取更多的照片?
或者是說使用更多的記憶體
這問題我真的查了很久都查不太到解答...
本來有查到說有人講我應該要用64位元的編譯器才行,
但我在想這樣32位元的系統不就不能執行了嗎?
而且有很多32位元的程式都會超過2G以上的不是嗎@@
不曉得有沒有高手可以指點一下的,拜託了
我寫了一個測試的讀檔程式放上來,不知道這樣有沒有違規,
有的話麻煩告知,我會速刪的。
這程式會讀取同資料夾下11.7MB的1.jpg圖檔,按一次按鈕會讀取五次
因為沒有寫執行緒,所以讀取過程會delay一段時間,
想說可以測試看看是不是真的『未使用』的部分不夠大時程式就無法讀取了。
https://mega.co.nz/#!UBsnCBSZ!hsvJ1ru5uU8KhL8zGoqsYww_3cINiUjK4Q3AAUzYQj0
不過寫了這程式反而讓我發現其他事情,
明明照片才11.7MB,可是開啟一次卻會讓程式佔用大約370M的記憶體
所以我自己的電腦只能開到三張,就沒辦法再開了
照片的大小是16744*5615,我把他相乘後再*4就是376M,
難道程式讀取照片佔用的記憶體是看這個@@?
我一直以為是看檔案大小,雖然發現這事情,不過問題還是存在ˇ_ˇ
拜託各位指點一下了,謝謝
--
※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 49.158.60.5
※ 文章網址: http://www.ptt.cc/bbs/C_and_CPP/M.1400609971.A.2C6.html
※ 編輯: googled (49.158.60.5), 05/21/2014 02:22:41
推
05/21 02:37, , 1F
05/21 02:37, 1F
是說記憶體釋放問題嗎@@?
可是我的確沒有要釋放讀取到的圖片
→
05/21 08:28, , 2F
05/21 08:28, 2F
→
05/21 08:29, , 3F
05/21 08:29, 3F
我了解了,謝謝解說
推
05/21 08:34, , 4F
05/21 08:34, 4F
所以最高最高就只能用到2G嗎@@
怪了...總覺得以前用XP 32位元時,玩遊戲時很容易就超過2G的說@@
還是真的是我記錯了
→
05/21 08:51, , 5F
05/21 08:51, 5F
所以說剩下800M都是分散的,因此沒有一塊完整376M的記憶體空間,所以才會當嗎
可是我程式讀取的圖片,每一張大約都會耗掉39M的記憶體
這樣的話只能讀取到1.2G的記憶體不是也怪怪的嗎@@
剩下的800M感覺沒有一個區塊是完整的39M挺怪的
推
05/21 09:08, , 6F
05/21 09:08, 6F
就像上面說的,是因為沒有完整的記憶體位置,所以才沒辦法讀取嚕@@
----------------
謝謝各位的解說,所以真的沒有其他辦法了嗎
※ 編輯: googled (49.158.60.5), 05/21/2014 11:20:42
→
05/21 12:30, , 7F
05/21 12:30, 7F
→
05/21 12:31, , 8F
05/21 12:31, 8F
→
05/21 12:39, , 9F
05/21 12:39, 9F
→
05/21 12:40, , 10F
05/21 12:40, 10F
→
05/21 12:42, , 11F
05/21 12:42, 11F
好的,其實聽你們這樣說也是,是我管理記憶體太差,
我這程式瀏覽圖片時有三種大小可以切換,分別是大張模式、中張模式、小張模式
大張模式一次顯示1張,中張是一次顯示6張,小張一次顯示36張
所以我程式一開始讀取圖片會縮放到大張模式該有的大小並丟進Vector(SourceImg)保存,
然後釋放原始圖片的記憶體
接著再看說使用者是用哪一種模式瀏覽照片,再從該SourceImg取出後縮放到符合的大小
所以這就是我會吃記憶體吃很兇的關係
本來是想說或許可以改成說需要用到哪些圖片,在臨時去開啟檔案就好,
沒有必要每張圖片都保存。
但我這程式可以提供修圖,像是R、G、B調整等等,
因此我另外又有一個Vector(ProcessImg)是儲存處理好的圖片
所以這就是我不釋放的原因,因為如果每次都把processImg跟SourceImg都釋放
要用到時才開檔並縮放,接著去處理像素,這樣會讓使用者等太久@@
而如果我不釋放的話,假設我現在在中張模式的第五頁,要顯示第30~36張的照片
就可以直接從ProcessImg取出第30~36張的照片並顯示,不需要讓使用者等待
而如果我要把第31張的照片拿來修圖,只需要從SourceImg取出第31張照片,
處理完像素後覆蓋到ProcessImg第31張的位置就可以了
這是我程式大概的流程,不曉得是不是有不妥的地方,拜託各位指導一下了
謝謝
※ 編輯: googled (49.158.60.5), 05/21/2014 13:27:21
→
05/21 13:11, , 12F
05/21 13:11, 12F
其實真的滿後悔沒有認真修作業系統的...
推
05/21 14:34, , 13F
05/21 14:34, 13F
→
05/21 14:35, , 14F
05/21 14:35, 14F
→
05/21 14:41, , 15F
05/21 14:41, 15F
→
05/21 14:42, , 16F
05/21 14:42, 16F
謝謝你的提供,所以是說我可以使用類似這種演算法來轉算接著再改圖
而不是像我每次使用者修圖時都是跑雙迴圈跑完所有的像素嚕@@
我都是用
for(int i=0 ; i < img.width() ; ++i)
for(int j=0 ; j < img.height() ; ++j){
//處理圖片
}
所以影像處理的速度都沒很快@@
※ 編輯: googled (49.158.60.5), 05/21/2014 15:37:28
→
05/21 17:44, , 17F
05/21 17:44, 17F
→
05/21 17:44, , 18F
05/21 17:44, 18F
推
05/21 18:20, , 19F
05/21 18:20, 19F
想請問一下為什麼先跑height會比較佳呢?
是因為照片都是橫的(width > height)較多的關係嗎?
→
05/21 18:23, , 20F
05/21 18:23, 20F
不好意思...小弟愚昧,請問什麼是每次處理32Bit跟SIMD Intrinsic是什麼意思?
推
05/21 18:25, , 21F
05/21 18:25, 21F
→
05/21 18:25, , 22F
05/21 18:25, 22F
→
05/21 18:25, , 23F
05/21 18:25, 23F
謝謝你,這軟體真的好用,還額外發現它可以抓出程式用了哪些DLL
不然我以前都還要把Qt的DLL一個個找出來測試
→
05/21 18:32, , 24F
05/21 18:32, 24F
推
05/21 18:35, , 25F
05/21 18:35, 25F
平行運算完全沒有學過跟碰過@@
不過應該是不需要到這麼快的地步,現在光是用uchar來處理像素速度就快了好多...
之前用雙迴圈跑img.pixmap(i,j)來處理3600*4500的像素要花大概1535毫秒
剛測是改成uchar後速度直接提升到94毫秒...
根本沒得比...
速度提升的的話或許就可以把一些圖片暫時釋放,讓程式不會佔用到太多記憶體
謝謝你的幫助
※ 編輯: googled (49.158.60.5), 05/21/2014 19:16:19
推
05/21 20:04, , 26F
05/21 20:04, 26F
原來如此,謝謝你的解說
→
05/21 20:06, , 27F
05/21 20:06, 27F
→
05/21 20:07, , 28F
05/21 20:07, 28F
請問用bitwise是不是跟操作uchar差不多@@?
昨天在網路上查到說用uchar可以加速QImage的處理速度
但是翻到QT的文檔又說不建議大家用uchar來操作,似乎是不安全的樣子
但換成bitwise來操作不知道有沒有這問題@@
(雖然本身也沒用過bitwise來改像素,還要在查查ˇ_ˇ)
QT文檔是說:
Warning: If you are accessing 32-bpp image data, cast the returned pointer to
QRgb* (QRgb has a 32-bit size) and use it to read/write the pixel value. You
cannot use the uchar* pointer directly, because the pixel format depends on
the byte order on the underlying platform. Use qRed(), qGreen(), qBlue(), and
qAlpha() to access the pixels.
→
05/21 20:10, , 29F
05/21 20:10, 29F
→
05/21 20:11, , 30F
05/21 20:11, 30F
→
05/21 20:11, , 31F
05/21 20:11, 31F
→
05/21 20:12, , 32F
05/21 20:12, 32F
→
05/21 20:14, , 33F
05/21 20:14, 33F
→
05/21 20:17, , 34F
05/21 20:17, 34F
→
05/21 20:18, , 35F
05/21 20:18, 35F
推
05/21 20:20, , 36F
05/21 20:20, 36F
→
05/21 20:25, , 37F
05/21 20:25, 37F
SIMD感覺難度好大ˇ_ˇ
果然自己不懂的地方還是好多,我今天在查說把Qt跟openCV結合
很多人都說openCV有優化過,所以速度絕對會比較快
就想把影像的部分都改成openCV來操作,但等於又要從0學習了
不過真的很謝謝你
※ 編輯: googled (49.159.8.95), 05/22/2014 21:18:13
推
05/22 21:49, , 38F
05/22 21:49, 38F
推
06/05 13:54, , 39F
06/05 13:54, 39F
C_and_CPP 近期熱門文章
PTT數位生活區 即時熱門文章