看板 MATLAB 關於我們 聯絡資訊
indx是一個index的向量,A和B是矩陣,我想把B中的某些元素放到A內 舉例來說: for i = 2:10000 A(idx(i),idx(1:i-1))=B(idx(i),idx(1:i-1)) end 請問有比較快的寫法嗎? -- ※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 111.184.40.155 ※ 文章網址: https://www.ptt.cc/bbs/MATLAB/M.1432827101.A.BA5.html
sean791121: 因為迴圈內的每一圈都處理不同大小的空間,所以不行用 05/28 23:34
sean791121: parfor 求比較快的方法 05/28 23:34
sunev: sub2ind 05/28 23:59
sean791121: 意思是用兩層for然後用sub2ind找位置嗎? 05/29 00:33
sean791121: 其實用一層loop也可以,我加速了快兩倍,可是和預期 05/29 00:45
sean791121: 的速度還是有落差,請問還有更快的寫法嗎? 05/29 00:45
celestialgod: 我測試了一下,A,B如果都是兩萬乘兩萬的矩陣 05/29 00:56
celestialgod: idx是長度10000,也只要2.345秒而已 05/29 00:57
celestialgod: 這樣還是不夠快嗎? 05/29 00:57
sean791121: cpu是i5 跑出來大概1.X秒 05/29 01:26
sean791121: 看文獻 Pentium 4 跑這段code再加上很多有的沒的 1秒 05/29 01:27
sean791121: 我猜文獻應該有用更快的方法 or我的演算法太爛了 05/29 01:28
sean791121: 對不起,忘記說明A和B都是sparse的 05/29 01:29
sean791121: A(sub_index)=B(sub_index)是不是比較慢呢? 05/29 01:30
sean791121: 因為matlab建議使用sparse(I,J,V,m,m) 05/29 01:31
celestialgod: 文獻也是用MATLAB? 而且你矩陣大小多少? 05/29 02:16
celestialgod: http://pastebin.com/D2jJSkRk MATLAB檔案 05/29 03:41
celestialgod: http://pastebin.com/JaUSthpX C++檔案 05/29 03:41
celestialgod: 我稍微試了一下,迴圈應該是MATLAB中最快的了 05/29 03:41
celestialgod: 要再加速就要靠MEX了,還不能複製input才做得到 05/29 03:41
celestialgod: 環境: MATLAB 2015a, windows 7 64bit, 05/29 03:42
celestialgod: [email protected] 05/29 03:42
sean791121: 文獻也是用MATLAB,我的矩陣5000乘5000 05/29 05:18
sean791121: 謝謝你提供方法,我會研究一下的 05/29 05:18
sean791121: 想請問您 為什麼matlab的速度會與C差這麼多? 05/29 05:22
sean791121: 因為MATLAB都會先判斷一些性質(矩陣、函數)的關係嗎? 05/29 05:23
sean791121: 對不起,我跑你的C++檔會出現bug,code沒問題呀XD 05/29 06:08
sunev: celestialgod太厲害了,可以想出這麼多寫法。 05/29 09:21
sunev: 我實際用c大給的code稍稍profile了一下。發現實際做出idx的 05/29 09:22
sunev: 方法(2~4),其實在真正assign的那行A(idx)=B(idx)並沒有比 05/29 09:23
sunev: 迴圈省下太多時間,所以算出idx的時間成本反而蓋過了直接 05/29 09:24
sunev: assign的效益。 05/29 09:24
sunev: 另外method 3中,應為triu(....,1),下面的 2:end可以去掉 05/29 09:26
celestialgod: 我昨天沒有想到一個可以直接產生idx的方法 05/29 09:27
sunev: 如果把(idx3>0)改成triu(true(mat_size,mat_size),1)會快 05/29 09:27
sunev: 一點,但仍比不上迴圈。 05/29 09:28
celestialgod: 我等等試試看,感謝 05/29 09:29
sunev: 另外我的經驗是,sparse在這種大量不規則assign的情況下 05/29 09:30
celestialgod: 原PO,我的c code,自己跑是沒問題的,我編譯的指令 05/29 09:31
celestialgod: 也在上面,你可能需要再研究一下。 05/29 09:31
sunev: 速度是慢了點,因為要一直改non-zero element很麻煩。 05/29 09:32
sunev: 所以官方才會建議用sparse一起解決。 05/29 09:33
celestialgod: 這裡sparse matrix不會比較快 05/29 09:34
celestialgod: 原po, c的速度會快本來就不意外..... 05/29 09:36
celestialgod: 這題只要想到怎樣產生(1, 1, 2, 1, 2, 3, 1, 2, 3, 05/29 09:38
celestialgod: 4, 1, 2, 3, 4, 5,... )的方法就會很快(不用矩陣 05/29 09:38
celestialgod: 取上三角... 這個會用到太多記憶體還是會慢) 05/29 09:38
sunev: 沒錯,不過true只要1byte,所以還好。XD 05/29 09:55
sunev: 剛發現不錯的寫法 05/29 10:43
sunev: A(idx,idx)=tril(B(idx,idx),-1)+triu(A(idx,idx)); 05/29 10:43
sunev: 但如果idx很大,B(idx,idx)這個sparse有可能會吃很多記憶體 05/29 10:44
celestialgod: 我測試的結果是assign反而比較久 05/29 10:57
celestialgod: 我算idx的時間大概0.5秒,assign要花2.1秒 05/29 10:57
celestialgod: 我也試著用gpuArray去算idx,但是還是卡在assign 05/29 10:59
sunev: 你矩陣是5000*5000,idx長度是10000嗎? 05/29 11:04
sunev: 這樣你矩陣還會是 "sparse" 嗎? 05/29 11:04
celestialgod: 5000*5000, 10000也只占0.04%..不過我用15000*15000 05/29 11:08
celestialgod: 我錯了XD,idx長度10000,要改將近5000萬個值 05/29 11:10
sunev: 我是問原作者啦。不確定他想加速到什麼程度,所以想確定 05/29 11:12
sunev: 問題的size 05/29 11:12
celestialgod: 剛剛有發現XDD 05/29 11:13
celestialgod: 如果assign的成本比算idx的成本還貴,這問題無解 05/29 11:14
celestialgod: 只能用C去更動矩陣的值才會快上不少 05/29 11:14
sunev: 再回樓上,我的意思不是assign比算idx久,而是一行assign 05/29 11:15
sunev: 比迴圈assign省不了多少時間,而算idx會超過省下的時間。 05/29 11:16
celestialgod: 喔喔,我懂了 05/29 11:17
celestialgod: 一行assign省下的時間沒有比算idx的時間短 05/29 11:18
sean791121: 對不起,K大概4800,謝謝兩位的幫忙 05/29 12:54