Closed YoheiKakiuchi closed 8 years ago
On Sat, Sep 26, 2015 at 3:47 PM, Yohei Kakiuchi notifications@github.com wrote:
verticesをN行3列 行列にしているんですが、Nが大きくなるとロード時間が Nx3要素のfloat-vectorに比べて大幅に時間がかかることがわかりました。 なのでベクトルを読んでから行列に入れています。
であれば,リーダで治せませんか?
◉ Kei Okada
リーダー見ているところですが、遅いのはリード自体ではなくて、その後のmatrixをつくるところですね。
ちゃんとプロファイルしてないですが、カンでみると、fill-initial-contentsの (elt seq i) が遅そうですね。
https://github.com/euslisp/EusLisp/blob/master/lisp/l/array.l#L71
seq (この場合は、行列の#2f
を除いたリストのリスト)が入っていて、
長いリストのeltは遅いので。
memset
があれば良いということでしょうか?
memsetがあれば良いということでしょうか?
#2f( (0 0 ... ) ... ) )
をリードするときに、 ( (0 0 ... ) ... ) )
としてリードしている[1]ので、
flattenしてベクトルにして(dolistができれば速度は同じくらいかも)という処理が必要かなと思います。
[1]のリストのリード部分を専用に作り変えるのは、そこそこ大事業な気がします。
なるほど、リストのeltが遅いんですね。 巧みにcar/cdrを駆使すれば出来そうな気もしますが
@YoheiKakiuchi
make-matrix 2 2 '(#f(1 2) #f(3 4))
でも遅いのかな. https://github.com/euslisp/EusLisp/blob/EusLisp-9.23/lisp/l/array.l#L124
#2f(...)
がこのPRの前の方法(方法1)
fvector-replace
がこのPRの方法(方法2)
make-matrix N 3 '(#f(....
が make-matrix 2 2 '(#f(1 2) #f(3 4))
この方法です。(方法3)
N = 100,1000,3000,10000,30000,100000
で時間を調べました。
1000以下だと方法2が遅いです。それより大きくなると逆転してもっとも小さいのが方法2です。
方法1と方法3はN^2のオーダー(方法3はもっと悪いかも)で方法2はNのオーダーのように見えます。
結論としては、大きいオーダーでは有効で、小さいオーダーではそもそも差が小さいので現状の方法2が良いように思います。
method / matrix size | 100 | 1000 | 3000 | 10000 | 30000 | 100000 |
---|---|---|---|---|---|---|
#2f(...) | 0.000194 | 0.006028 | 0.017283 | 0.096926 | 0.803124 | 8.70069 |
fvector-replace | 0.004523 | 0.004375 | 0.005983 | 0.011543 | 0.026517 | 0.08314 |
make-matrix N 3 '(#f(.... | 0.000267 | 0.002115 | 0.011014 | 0.091801 | 0.795989 | 15.8223 |
https://github.com/euslisp/EusLisp/pull/139 にも関係するんですが、 verticesをN行3列 行列にしているんですが、Nが大きくなるとロード時間が Nx3要素のfloat-vectorに比べて大幅に時間がかかることがわかりました。 なのでベクトルを読んでから行列に入れています。 これでjaxon_redのロード時間が半分くらいになります。