computer-graphics-mass-spring-systems icon indicating copy to clipboard operation
computer-graphics-mass-spring-systems copied to clipboard

Animation is slow for sparse implementation

Open shimismith opened this issue 5 years ago • 8 comments

After switching to sparse matrices the pre-computation is significantly faster but the animation is still quite slow. If I created Q and b using multiplications and additions should they still be stored efficiently? The solve() part is what is bottlenecking the application here.

shimismith avatar Dec 04 '19 01:12 shimismith

Yes, adding and multiplying sparse matrices still produces a sparse matrix.

Are you running your code in debug mode, or running the skirt example without wind? If the former is true, you shouldn't be looking at performance. If the latter is true, some other students noticed some slow behaviour as the skirt falls without wind, so it might not indicate a bug in your code - try turning on wind before running the animation, and see if this produces something like the gif in the readme.

abhimadan avatar Dec 04 '19 01:12 abhimadan

I'm running in release mode and even the flag is still quite slow. It's pretty far from being a smooth animation.

shimismith avatar Dec 04 '19 02:12 shimismith

One other problem some other students had was converting dense matrices to sparse matrices. Things like Ucur and Uprev are dense, and converting them to sparse matrices significantly slows things down. Eigen directly supports multiplication between dense and sparse matrices, so you don't need to do any other preprocessing to get that to work.

abhimadan avatar Dec 04 '19 02:12 abhimadan

Thanks for the suggestions. Unfortunately, I'm not converting any dense matrices to sparse.

shimismith avatar Dec 04 '19 02:12 shimismith

In case by some absurd chance someone has the same problem as me. It was because I was putting the formula that evaluates to b straight into the .solve(...) but I changed it to creating a temporary Eigen::MatrixXd variable. I'm honestly quite confused as to why this made such a huge difference but I'm guessing I had stuff in some weird format and casting it to a dense matrix did the trick.

shimismith avatar Dec 04 '19 04:12 shimismith

Glad you found it.

b should dense.

The expression issue could be a known issue with Eigen. After a few days after the deadline could post it here?

On Tue, Dec 3, 2019, 11:29 PM shimismith [email protected] wrote:

In case by some absurd chance someone has the same problem as me. It was because I was putting the formula that evaluates to b straight into the .solve(...) but I changed it to creating a temporary Eigen::MatrixXd variable. I'm honestly quite confused as to why this made such a huge difference but I'm guessing I had stuff in some weird format and casting it to a dense matrix did the trick.

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/alecjacobson/computer-graphics-mass-spring-systems/issues/22?email_source=notifications&email_token=AARDJGPGAEYB4LDC3ACXC5DQW4WZ5A5CNFSM4JVBFWE2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEF3WBNI#issuecomment-561471669, or unsubscribe https://github.com/notifications/unsubscribe-auth/AARDJGOYVKGIBI4QNBSUPKLQW4WZ5ANCNFSM4JVBFWEQ .

alecjacobson avatar Dec 04 '19 04:12 alecjacobson

Sorry for taking a while to get back to you about this.

Initially I had,

Unext = prefactorization.solve(k*A.transpose()*d + (1/(delta_t*delta_t))*M*(2*Ucur - Uprev) + fext + 1e10*C.transpose()*C*V);
and it was running very slowly.

Then I changed it to,

Eigen::MatrixXd y = k*A.transpose()*d + (1/(delta_t*delta_t))*M*(2*Ucur - Uprev) + fext + 1e10*C.transpose()*C*V;
Unext = prefactorization.solve(y);

shimismith avatar Dec 18 '19 23:12 shimismith

My guess is that this is caused by lazy evaluation. In Eigen, matrix expressions are only evaluated when needed. When you assign a matrix expression to a Matrix type, it will be forced to evaluate it, but the solver takes an EigenBase, which can be a lazy expression, so it doesn't see the need to evaluate it until the actual solve. Unfortunately, the solver's probably not caching the evaluated expression, so it's re-evaluating it any time it needs to access any of its entries.

abhimadan avatar Dec 19 '19 00:12 abhimadan