看板 C_and_CPP 關於我們 聯絡資訊
簡單的說,因專案裡用到 MFC CArray 變數,但 CArray 記憶體管理 在某個函式裡有缺陷,我想自己手動控,不過這個 CArray 變數在其 他地方使用太頻繁,不可能切掉重練,所以想先用 C native code 做完記憶體管理與運算後,再將相關資訊塞回 CArray 裡,以下是我 的 Code , 不過當然造成了 compile error... template<typename T1, typename T2> void NativeAryToCArray( CArray<T1, T2> & cary, T1 * pBuf , const INT_PTR nSize, const INT_PTR nMaxSize, const INT_PTR nGrowBy) { ((char*)&cary + 4) = (char*)pBuf; // error C2106 char * pAddr= (char *)&cary + sizeof(T1*); *(INT_PTR*)pAddr = nSize; pAddr+=sizeof(INT_PTR); *(INT_PTR*)pAddr = nMaxSize; pAddr+=sizeof(INT_PTR); *(INT_PTR*)pAddr = nGrowBy; } --- 問題主要有三 (1) pBuf 那段怎麼塞回去? (2) 若考慮可能會換 vs 版本的問題,該怎麼做比較具相容性? ( 雖然我覺得不太可能 ) (3) 請問我想要的目的,該怎麼做比較漂亮? 目前最大瓶頸在於,SetSize 會自動呼叫 memset , 這動作讓我產生了兩難.. (3.1) 只要調用 SetSize ,時間花在 memset (3.2) 不用 SetSize ,每次用 Add 的話時間噴更多 (何況 Add 最後還是會 SetSize) 在想不到有什麼方法可以避免 memset 花費,只好出此下策。 先謝謝各位不吝指教,感激不盡。 -- ~ 這輩子與神手無緣 我只好當神獸了 ~ 卡卡獸 -- ※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 180.177.73.224 ※ 文章網址: http://www.ptt.cc/bbs/C_and_CPP/M.1396640500.A.415.html
freaky:你的問題蠻奇怪的,你真的確定memset是瓶頸嗎? 04/05 04:32
freaky:一般來說應該是copy/reallocation太頻繁導致效能不佳 04/05 04:48
freaky:因為CArray是線性成長 04/05 04:50
推文不便抱歉中斷了。 我不太確定線性成長定義為何,但我知道一次是以 nGrowBy 為單位在增長。 這點和 vector 策略有異,然後的確 copy / reallocation 太差,所以改成 事先一次 SetSize 大一點的 Buf , 使 Add 機會變小 , 所以 trace 下來瓶 變 memset ( 約 1/5 時間 ) , 這點我待有環境時再確認過。
kiedveian:*(char**)((char*)&cary + 4) = (char*)pBuf; 04/05 12:25
kiedveian:這樣不知道行不行 04/05 12:25
這裡過了 , 謝謝!!
dirkc:記得MFC有source,從那裡下手的可能性?另外所說的缺陷是指? 04/08 18:48
事後想,其實也不能說是 CArray 的缺陷,只是我想要省下一些時間。 (1) CArray::SetSize, vector::resize , 不論是哪一個,都有 memset 的動作 , 但我的例子根本就不用初始化。這點會計較,原因是記憶 體使用量大。 (2) 也由於記憶體使用量大,在智能成長,計算完後會再呼叫 FreeExtra, 但進去 trace code, 它的作法讓我蠻傻眼的,是先額外配置另外一份 新的記憶體,舊的填進去,新的拿來用,舊的再放掉。這在我的想法 應該用 realloc 就不一定會配置一份新的。 (3) 其實以我的例子來講,智能成長是以 vector 較為合適的,但這裡不論 是 vector / CArray,要自己動手利用內部現有的函式做配置策略,就 顯得有些繞路。
freaky:不建議改MFC,可以在呼叫端利用SetSize()改變成長曲線 04/08 19:22
freaky:線性成長y=Mx,x為成長次數,M為每次增加的element 04/08 19:24
freaky:Standard C++ Library的成長曲線是y=K^N 04/08 19:29
的確我也不敢改 MFC source code, 那裡不只我一個人在用而已。 最後還是放棄硬塞回去的念頭,最後做法如 freaky 所言,用 SetSize 做智能配置入口,原本是用 CArray<POD_TYPE,POD_TYPE> ary[ARY_CNT]; 除了先估 INT_PRT nGrowList[] 當智能策略外,還要再多份 INT_PTR nAryCount[ARY_CNT]; 去記錄目前每份 array 的容量是多少,再來是增長失敗時的處理, 這些動作的確 CArray / vector 都做得到,只是記憶體用量已到極限, 要用包好的東西處理就顯得麻煩些了。 改完後的 Code ,效能的確提昇不少便是。謝謝各位關注 :D ※ 編輯: EdisonX (180.177.73.224), 04/08/2014 23:41:19