[閒聊] AppendTo 指令的效率替代方案

作者: ginstein (邁向學術之路)   2016-10-12 18:54:54
借 AmibaGelos 的文討論一下 MMA 中 AppendTo 的效率替代方案,
因為 AppendTo 的指令每次重新複製一次再加入新元素,又慢又吃記憶體,
但是 AppendTo/PrependTo名字取的好,所以造成許多無效率程式碼,
像是 Jon McLoone 的 10 Tips for Writing Fast Mathematica Code 中
7. Use Sow and Reap to accumulate large amounts of data (not AppendTo).
建議用 Sow and Reap 替代 AppendTo,
另外用 linked lists,例如以 set = {set, new} 取代 AppendTo[set,new]
最後再 Flatten,會有效率得多。
(A大的例子要多設個新head含seed相資訊, set = {set, infohead[newinfos]}),
找到一個相關網頁,連效率比較圖都畫出來給大家看:
http://
stackoverflow.com/questions/8450779/prepend-vs-append-perf-in-mathematica
看了一下內文比較 AppendTo, linked lists 和 Join 指令的效率,
用 Join 最快,不過我覺得合理情況下應該用 set = Join[set, new] 指令來比較,
而不是 Join[startlist, datalist=Table[newdata,...]]來比較效率。
※ 引述《AmibaGelos (Amiba Gelos)》之銘言:
: 最近在用MMA跑Monte Carlo,覺得MMA不能提取seed實在是很不方便,所以就做了一個可以
: 提取seed的RandomVariate
: Module[{seed, store = {}, temp = 1, Storing},
: RandomMemory[1, opt___] := RandomMemory[temp, opt];
: RandomMemory[in__] := (Storing[in]; RandomVariate[in]);
: Storing[dist_, opt___] :=
: AppendTo[
: store, {Evaluate[If[dist === temp, 1, temp = dist]], opt}];
: SetSeed[InSeed_, InStore_: {}] := (store = {}; temp = 1;
: SeedRandom[seed = InSeed]; (RandomMemory[##];) & @@@ InStore;);
: ExtractSeed[] := {seed, store}; SetSeed[0];];
: 這個設計在跑custom distribution的時候蠻好用的, 不過AppendTo會是瓶頸
: 目前只有想到hash, 不過有新distribution還是得重建table
: 不知道有沒有更漂亮的寫法?
作者: AmibaGelos (Amiba Gelos)   2016-10-12 21:50:00
Linkedlist要做container速度不會比Join快吧join速度很快蠻怪的...這樣Append/Prepend是做心酸嗎
作者: ginstein (邁向學術之路)   2016-10-12 22:11:00
最快應該是Sow/Reap,最適合A大題目的應該是linkedlistsJoin最快是因為測試碼直接生成所需資料再Join,當然最快Join連資料的速度比Flatten指令解linkedlist結構快的若loop中用set=Join[set,new]的話,Join不會比較快
作者: AmibaGelos (Amiba Gelos)   2016-10-12 22:18:00
喔喔這樣看來確實是該用linkedlist!

Links booklink

Contact Us: admin [ a t ] ucptt.com